This is a cleaned version of 04_24_19 Temp link trait fish.Rmd/11_20_19_Temp_link_traits_fish.Rmd. Changes * improved formatting * easier to follow * species and region as random effects * scaling temperature values * setting nACQ to 0, see why here.

August 11, 2022: Working on Revisions from Global Ecology and Biogeography * Add random effects for order, genus, family, etc.

library(MuMIn)
library(lme4)
Loading required package: Matrix

Attaching package: ‘Matrix’

The following objects are masked from ‘package:tidyr’:

    expand, pack, unpack
library(data.table)
library(ggplot2)
library(here)
library(wesanderson) # to color plots
library(taxize) #to obtain order, genus, family
library(dplyr)
library(DHARMa)
Warning: package ‘DHARMa’ was built under R version 4.1.2
This is DHARMa 0.4.5. For overview type '?DHARMa'. For recent changes, type news(package = 'DHARMa')
spp_master_ztemp_seus_buoy_scaled <- readRDS(here("Data","Spp_master", "spp_master_ztemp_seus_buoy_scaled.rds"))

Link up with spp key to add phylum, order, family, etc.

spp_key <- fread(here::here("Data","Spp_master","spp_key.csv"))

spp_master_ztemp_seus_buoy_scaled <- spp_master_ztemp_seus_buoy_scaled[spp_key, on = "spp"]

    

Running, and ranking arrival models without traits

##Here, I scaled all temperature values across all regions, and included species as a random effect. In order to do this, I had to change the algorithm slightly–nAGQ = 0.

Gain/Arrival Models with Additional random effects

#names of scaled columns
variables_scaled <- grep("*_scaled", names(spp_master_ztemp_seus_buoy_scaled), value = T)
#going to make loop to make all models I need to look at with a single temperature variable

arrival_model_comparison_taxonomy <- as.data.table(matrix(nrow = length(variables_scaled)))
arrival_model_comparison_taxonomy[, variable:=as.factor(V1)][, coef:=as.numeric(V1)][, p_value:=as.numeric(V1)][, AICc:=as.numeric(V1)]
arrival_model_comparison_taxonomy[, V1 := NULL]

for (i in 1:length(variables_scaled)){
  mod <- glmer(col ~ get(variables_scaled[i]) + (1|reg) + (1|phylum) + (1|class) + (1|order) + (1|family) + (1|genus) + (1|spp),
               family = binomial, data = spp_master_ztemp_seus_buoy_scaled, nAGQ = 0)
  arrival_model_comparison_taxonomy[i,variable := variables_scaled[i]]
  arrival_model_comparison_taxonomy[i,coef := coef(summary(mod))[,"Estimate"][2]]
  arrival_model_comparison_taxonomy[i,p_value := coef(summary(mod))[,"Pr(>|z|)"][2]]
  arrival_model_comparison_taxonomy[i,AICc := AICc(mod)]
  
  print(paste(i, length(variables_scaled), sep = "/"))
    
}

#by setting nACQ to 0, all models converged

saveRDS(object = arrival_model_comparison_taxonomy, file = here("Model_results","arrival_model_results_taxonomy.rds"))
fwrite(arrival_model_comparison_taxonomy, file = here("Model_results","arrival_model_results_taxonomy.csv"))
arrival_model_comparison_taxonomy <- readRDS(here::here("Model_results","arrival_model_results_taxonomy.rds"))

Model performance and assumptions.

#group by region
simulationOutput <- simulateResiduals(fittedModel = mod_extrarandom_gain)
simulationOutput.groupedbyreg <- recalculateResiduals(simulationOutput, group = spp_master_ztemp_seus_buoy_scaled.r$reg)
testDispersion(simulationOutput)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs.
    simulated

data:  simulationOutput
dispersion = 0.48913, p-value = 0.008
alternative hypothesis: two.sided

testDispersion(simulationOutput.groupedbyreg)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs.
    simulated

data:  simulationOutput
dispersion = 0.33711, p-value = 0.592
alternative hypothesis: two.sided

plot(simulationOutput.groupedbyreg)
DHARMa:testOutliers with type = binomial may have inflated Type I error rates for integer-valued distributions. To get a more exact result, it is recommended to re-run testOutliers with type = 'bootstrap'. See ?testOutliers for details
qu = 0.25, log(sigma) = -2.803254 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -2.762825 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -2.928257 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -3.005512 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -3.082768 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -3.987401 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -4.089001 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -4.262087 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -4.28162 : outer Newton did not converge fully.
qu = 0.25, log(sigma) = -4.281743 : outer Newton did not converge fully.

#group by spp
simulationOutput.groupedbyspp <- recalculateResiduals(simulationOutput, group = spp_master_ztemp_seus_buoy_scaled.r$spp)
testDispersion(simulationOutput)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs.
    simulated

data:  simulationOutput
dispersion = 0.48913, p-value = 0.008
alternative hypothesis: two.sided

testDispersion(simulationOutput.groupedbyspp)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs.
    simulated

data:  simulationOutput
dispersion = 0.22649, p-value < 2.2e-16
alternative hypothesis: two.sided

plot(simulationOutput.groupedbyspp)
DHARMa:testOutliers with type = binomial may have inflated Type I error rates for integer-valued distributions. To get a more exact result, it is recommended to re-run testOutliers with type = 'bootstrap'. See ?testOutliers for details

“The estimate for seasonality of -0.49 means that a 1 degree increase in seasonality is associated with a 0.49 decrease in the log-odds of a Gain occuring, compared to no Gain occuring. If we exponentiate this number then we obtain the odds ratio of 0.6108308, which means that for a 1 degree increase in Seasonality we expect to see (approximately) a 39% decrease in the odds of a Gain Occurring.” From this Stack Exchange post.

###Departure Models without Traits but with random effects for phylogeny

#group by region
simulationOutput_loss <- simulateResiduals(fittedModel = mod_extrarandom_loss)
simulationOutput.groupedbyreg_loss <- recalculateResiduals(simulationOutput_loss, group = spp_master_ztemp_seus_buoy_scaled.r$reg)
testDispersion(simulationOutput_loss)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 0.61949, p-value = 0.08
alternative hypothesis: two.sided

testDispersion(simulationOutput.groupedbyreg_loss)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 0.56908, p-value = 0.976
alternative hypothesis: two.sided

plot(simulationOutput.groupedbyreg_loss)
DHARMa:testOutliers with type = binomial may have inflated Type I error rates for integer-valued distributions. To get a more exact result, it is recommended to re-run testOutliers with type = 'bootstrap'. See ?testOutliers for details

#no random effects
simulationOutput_loss_noRE <- simulateResiduals(fittedModel = mod_extrarandom_loss_noRE)
simulationOutput.groupedbyreg_loss_noRE <- recalculateResiduals(simulationOutput_loss_noRE, group = spp_master_ztemp_seus_buoy_scaled.r$reg)
testDispersion(simulationOutput_loss_noRE)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 1.0002, p-value = 0.936
alternative hypothesis: two.sided

testDispersion(simulationOutput.groupedbyreg_loss_noRE)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 27.227, p-value < 2.2e-16
alternative hypothesis: two.sided

plot(simulationOutput.groupedbyreg_loss_noRE)
DHARMa:testOutliers with type = binomial may have inflated Type I error rates for integer-valued distributions. To get a more exact result, it is recommended to re-run testOutliers with type = 'bootstrap'. See ?testOutliers for details

#group by spp
simulationOutput.groupedbyspp_loss <- recalculateResiduals(simulationOutput_loss, group = spp_master_ztemp_seus_buoy_scaled.r$spp)
testDispersion(simulationOutput_loss)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 0.61949, p-value = 0.08
alternative hypothesis: two.sided

testDispersion(simulationOutput.groupedbyspp_loss)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 0.29456, p-value = 0.04
alternative hypothesis: two.sided

plot(simulationOutput.groupedbyspp_loss)
DHARMa:testOutliers with type = binomial may have inflated Type I error rates for integer-valued distributions. To get a more exact result, it is recommended to re-run testOutliers with type = 'bootstrap'. See ?testOutliers for details

#with no random effects
simulationOutput.groupedbyspp_loss_noRE <- recalculateResiduals(simulationOutput_loss_noRE, group = spp_master_ztemp_seus_buoy_scaled.r$spp)
testDispersion(simulationOutput_loss_noRE)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 1.0002, p-value = 0.936
alternative hypothesis: two.sided

testDispersion(simulationOutput.groupedbyspp_loss_noRE)

    DHARMa nonparametric dispersion test via sd of residuals fitted vs. simulated

data:  simulationOutput
dispersion = 3.251, p-value < 2.2e-16
alternative hypothesis: two.sided

plot(simulationOutput.groupedbyspp_loss_noRE)
DHARMa:testOutliers with type = binomial may have inflated Type I error rates for integer-valued distributions. To get a more exact result, it is recommended to re-run testOutliers with type = 'bootstrap'. See ?testOutliers for details

“The estimate for seasonality of -0.3242 means that a 1 degree increase in seasonality is associated with a 0.3242 decrease in the log-odds of a Loss occuring, compared to no Loss occuring. If we exponentiate this number then we obtain the odds ratio of 0.7231, which means that for a 1 degree increase in Seasonality we expect to see (approximately) a 18% decrease in the odds of a Loss Occurring.” From this Stack Exchange post.

##Relative Variable Importance

NB: I didn’t end up using mean as a predictor variable (patterns captured in min and max, less relevant to thermal niche)

arrival_model_comparison_nomean <- arrival_model_comparison_taxonomy[!grepl("mean",variable),]

departure_model_comparison_nomean <- departure_model_comparison_taxonomy[!grepl("mean",variable),]

How does the null model with only random effects perform?

#add null to tables
intercept_arrival_mod_scaled <- glmer(col ~ + (1|reg) + (1|phylum) + (1|class) + (1|order) + (1|family) + (1|genus) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled, nAGQ = 0)

r.squaredGLMM(intercept_arrival_mod_scaled)

intercept_departure_mod_scaled <- glmer(now_ext ~ + (1|reg) + (1|phylum) + (1|class) + (1|order) + (1|family) + (1|genus) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled, nAGQ = 0)

r.squaredGLMM(intercept_departure_mod_scaled)

#best model better than null? yes
AICc(intercept_arrival_mod_scaled)-AICc(mod_extrarandom_gain)
AICc(intercept_departure_mod_scaled)-AICc(mod_extrarandom_loss)

How do other loss models perform with AICc less than 0.05?


mod_extrarandom_loss_2 <- glmer(now_ext ~ seas_sst_temp_change_lag2_scaled  + (1|reg) + (1|phylum) + (1|class) + (1|order) + (1|family) + (1|genus) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled, nAGQ = 0)
r.squaredGLMM(mod_extrarandom_loss_2)

mod_extrarandom_loss_3 <- glmer(now_ext ~ min_sst_temp_change_lag2_scaled  + (1|reg) + (1|phylum) + (1|class) + (1|order) + (1|family) + (1|genus) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled, nAGQ = 0)
r.squaredGLMM(mod_extrarandom_loss_3)

Relative Variable Importance for Arrival Models

#add ∆AIC to tables
min_arrival_AICc <- min(arrival_model_comparison_nomean[, AICc])
arrival_model_comparison_nomean[,"deltaAICc" := (AICc - min_arrival_AICc)]

#add relative likelihood exp( -0.5 * ∆AIC score for that model)
arrival_model_comparison_nomean[,"rel_likelihood" := exp((-0.5 * deltaAICc))]
#sum relative likelihoods across all models
arrival_model_comparison_nomean.likelihoodsum <- sum(arrival_model_comparison_nomean[, rel_likelihood])
#Akaike weight for a model is this rel_likelihood divided by the sum of these values across all models
arrival_model_comparison_nomean[,"akaike_weight" := rel_likelihood/arrival_model_comparison_nomean.likelihoodsum]

#I want to look at relative importance FOR:

#bottom/surface (bottom = includes sbt, grepl("sbt", variable))
arrival_bottom_importance <- sum(arrival_model_comparison_nomean[grep("sbt", variable), ]$akaike_weight)
arrival_surface_importance <- sum(arrival_model_comparison_nomean[grep("sst", variable), ]$akaike_weight)

#lag/not lagged (grepl("lag", variable))
arrival_lag_importance <- sum(arrival_model_comparison_nomean[grep("lag", variable), ]$akaike_weight)
arrival_nolag_importance <- sum(arrival_model_comparison_nomean[!grep("lag", variable), ]$akaike_weight)

#absolute (grepl("abs", variable))
arrival_abs_importance <- sum(arrival_model_comparison_nomean[grep("abs", variable), ]$akaike_weight)

#raw (!grepl("change"))
arrival_raw_importance <- sum(arrival_model_comparison_nomean[!grep("change", variable), ]$akaike_weight)

#change (grepl("change", variable), (!grepl("abs")))
arrival_change_importance <- sum(arrival_model_comparison_nomean[grep("change", variable), ][!grep("abs", variable),]$akaike_weight)

#type of temp variable (max, min, seas)
arrival_max_temp_importance <- sum(arrival_model_comparison_nomean[grep("max", variable), ]$akaike_weight)
arrival_min_temp_importance <- sum(arrival_model_comparison_nomean[grep("min", variable), ]$akaike_weight)
arrival_seas_temp_importance <- sum(arrival_model_comparison_nomean[grep("seas", variable), ]$akaike_weight)

arrival_model_comparison_nomean_akaikeweights <- arrival_model_comparison_nomean

saveRDS(arrival_model_comparison_nomean_akaikeweights, file = here("Model_results","arrival_model_comparison_nomean_akaikeweights.rds"))
saveRDS(arrival_model_comparison_nomean_akaikeweights, file = here("tables","arrival_model_comparison_nomean_akaikeweights.rds"))
arrival_model_comparison_nomean_akaikeweights <- readRDS(file = here("Model_results","arrival_model_comparison_nomean_akaikeweights.rds"))

Relative Variable Importance for different Pairs of Transformation and Metric


#I want to look at relative importance FOR 
#models with raw and min
arrival_raw_min_importance <- sum(arrival_model_comparison_nomean[grep("min", variable), ][!grep("change", variable)]$akaike_weight)

#models with raw and max
arrival_raw_max_importance <- sum(arrival_model_comparison_nomean[grep("max", variable), ][!grep("change", variable)]$akaike_weight)

#models with raw and seas
arrival_raw_seas_importance <- sum(arrival_model_comparison_nomean[grep("seas", variable), ][!grep("change", variable)]$akaike_weight)


#models with change and min
arrival_change_min_importance <- sum(arrival_model_comparison_nomean[grep("min_s.t_temp_change", variable), ][!grep("abs", variable)]$akaike_weight)

#models with change and max
arrival_change_max_importance <- sum(arrival_model_comparison_nomean[grep("max_s.t_temp_change", variable), ][!grep("abs", variable)]$akaike_weight)

#models with change and seas
arrival_change_seas_importance <- sum(arrival_model_comparison_nomean[grep("seas_s.t_temp_change", variable), ][!grep("abs", variable)]$akaike_weight)

#models with abs change and min
arrival_abs_change_min_importance <- sum(arrival_model_comparison_nomean[grep("min_s.t_temp_change_abs", variable), ]$akaike_weight)

#models with abs change and max
arrival_abs_change_max_importance <- sum(arrival_model_comparison_nomean[grep("max_s.t_temp_change_abs", variable), ]$akaike_weight)

#models with abs change and seas
arrival_abs_change_seas_importance <- sum(arrival_model_comparison_nomean[grep("seas_s.t_temp_change_abs", variable), ]$akaike_weight)

arrival_transform_metric_comparison <- data.table(Transformation =
                                                c("raw", "raw", "raw", "change", "change", "change", "abs_change", "abs_change", "abs_change"), 
                                              Metric = 
                                                rep(c("min", "max", "seas"), 3), 
                                              RVI = 
                                                c(arrival_raw_min_importance, arrival_raw_max_importance, 
                                                  arrival_raw_seas_importance, arrival_change_min_importance, 
                                                  arrival_change_max_importance, arrival_change_seas_importance, 
                                                  arrival_abs_change_min_importance, arrival_abs_change_max_importance, 
                                                  arrival_abs_change_seas_importance))

Relative Variable Importance Departure Models

#add ∆AIC to tables
min_departure_AICc <- min(departure_model_comparison_nomean[, AICc])
departure_model_comparison_nomean[,"deltaAICc" := (AICc - min_departure_AICc)]

#add relative likelihood exp( -0.5 * ∆AIC score for that model)
departure_model_comparison_nomean[,"rel_likelihood" := exp((-0.5 * deltaAICc))]
#sum relative likelihoods across all models
departure_model_comparison_nomean.likelihoodsum <- sum(departure_model_comparison_nomean[, rel_likelihood])
#Akaike weight for a model is this rel_likelihood devided by the sum of these values across all models
departure_model_comparison_nomean[,"akaike_weight" := rel_likelihood/departure_model_comparison_nomean.likelihoodsum]

#I want to look at relative importance FOR 
#bottom/surface (bottom = includes sbt, grepl("sbt", variable))
departure_bottom_importance <- sum(departure_model_comparison_nomean[grep("sbt", variable), ]$akaike_weight)
departure_surface_importance <- sum(departure_model_comparison_nomean[grep("sst", variable), ]$akaike_weight)

#lag/not lagged (grepl("lag", variable))
departure_lag_importance <- sum(departure_model_comparison_nomean[grep("lag", variable), ]$akaike_weight)
departure_nolag_importance <- sum(departure_model_comparison_nomean[!grep("lag", variable), ]$akaike_weight)

#absolute (grepl("abs", variable))
departure_abs_importance <- sum(departure_model_comparison_nomean[grep("abs", variable), ]$akaike_weight)

#raw (!grepl("change"))
departure_raw_importance <- sum(departure_model_comparison_nomean[!grep("change", variable), ]$akaike_weight)

#change (grepl("change", variable), (!grepl("abs")))
departure_change_importance <- sum(departure_model_comparison_nomean[grep("change", variable), ][!grep("abs", variable),]$akaike_weight)

#type of temp variable (max, min, seas)
departure_max_temp_importance <- sum(departure_model_comparison_nomean[grep("max", variable), ]$akaike_weight)
departure_min_temp_importance <- sum(departure_model_comparison_nomean[grep("min", variable), ]$akaike_weight)
departure_seas_temp_importance <- sum(departure_model_comparison_nomean[grep("seas", variable), ]$akaike_weight)

departure_model_comparison_nomean_akaikeweights <- departure_model_comparison_nomean

saveRDS(departure_model_comparison_nomean_akaikeweights, file = here("Model_results","departure_model_comparison_nomean_akaikeweights.rds"))
saveRDS(departure_model_comparison_nomean_akaikeweights, file = here("tables","departure_model_comparison_nomean_akaikeweights.rds"))
departure_model_comparison_nomean_akaikeweights <- readRDS(file = here("Model_results","departure_model_comparison_nomean_akaikeweights.rds"))

Relative Variable Importance for Pairs of Transformation and Metric Predicting departures


#I want to look at relative importance FOR 
#models with raw and min
departure_raw_min_importance <- sum(departure_model_comparison_nomean[grep("min", variable), ][!grep("change", variable)]$akaike_weight)

#models with raw and max
departure_raw_max_importance <- sum(departure_model_comparison_nomean[grep("max", variable), ][!grep("change", variable)]$akaike_weight)

#models with raw and seas
departure_raw_seas_importance <- sum(departure_model_comparison_nomean[grep("seas", variable), ][!grep("change", variable)]$akaike_weight)


#models with change and min
departure_change_min_importance <- sum(departure_model_comparison_nomean[grep("min_s.t_temp_change", variable), ][!grep("abs", variable)]$akaike_weight)

#models with change and max
departure_change_max_importance <- sum(departure_model_comparison_nomean[grep("max_s.t_temp_change", variable), ][!grep("abs", variable)]$akaike_weight)

#models with change and seas
departure_change_seas_importance <- sum(departure_model_comparison_nomean[grep("seas_s.t_temp_change", variable), ][!grep("abs", variable)]$akaike_weight)

#models with abs change and min
departure_abs_change_min_importance <- sum(departure_model_comparison_nomean[grep("min_s.t_temp_change_abs", variable), ]$akaike_weight)

#models with abs change and max
departure_abs_change_max_importance <- sum(departure_model_comparison_nomean[grep("max_s.t_temp_change_abs", variable), ]$akaike_weight)

#models with abs change and seas
departure_abs_change_seas_importance <- sum(departure_model_comparison_nomean[grep("seas_s.t_temp_change_abs", variable), ]$akaike_weight)

departure_transform_metric_comparison <- data.table(Transformation =
                                                c("raw", "raw", "raw", "change", "change", "change", "abs_change", "abs_change", "abs_change"), 
                                              Metric = 
                                                rep(c("min", "max", "seas"), 3), 
                                              RVI = 
                                                c(departure_raw_min_importance, departure_raw_max_importance, 
                                                  departure_raw_seas_importance, departure_change_min_importance, 
                                                  departure_change_max_importance, departure_change_seas_importance, 
                                                  departure_abs_change_min_importance, departure_abs_change_max_importance, 
                                                  departure_abs_change_seas_importance))

Let’s see how the RVI importance varies by looking at specific lag values


#first, table for lags
lags_RVI_scaled <- data.table(arrival_lag = c(0:9), arrival_RVI = 0, departure_RVI = 0)

#arrivals
lags_RVI_scaled[1,2] <- 1-sum(arrival_model_comparison_nomean[grep("lag", variable), ]$akaike_weight)
lags_RVI_scaled[2,2] <- sum(arrival_model_comparison_nomean[grep("lag1", variable), ]$akaike_weight)
lags_RVI_scaled[3,2] <- sum(arrival_model_comparison_nomean[grep("lag2", variable), ]$akaike_weight)
lags_RVI_scaled[4,2] <- sum(arrival_model_comparison_nomean[grep("lag3", variable), ]$akaike_weight)
lags_RVI_scaled[5,2] <- sum(arrival_model_comparison_nomean[grep("lag4", variable), ]$akaike_weight)
lags_RVI_scaled[6,2] <- sum(arrival_model_comparison_nomean[grep("lag5", variable), ]$akaike_weight)
lags_RVI_scaled[7,2] <- sum(arrival_model_comparison_nomean[grep("lag6", variable), ]$akaike_weight)
lags_RVI_scaled[8,2] <- sum(arrival_model_comparison_nomean[grep("lag7", variable), ]$akaike_weight)
lags_RVI_scaled[9,2] <- sum(arrival_model_comparison_nomean[grep("lag8", variable), ]$akaike_weight)
lags_RVI_scaled[10,2] <- sum(arrival_model_comparison_nomean[grep("lag9", variable), ]$akaike_weight)

#departures
lags_RVI_scaled[1,3] <- 1-sum(departure_model_comparison_nomean[grep("lag", variable), ]$akaike_weight)
lags_RVI_scaled[2,3] <- sum(departure_model_comparison_nomean[grep("lag1", variable), ]$akaike_weight)
lags_RVI_scaled[3,3] <- sum(departure_model_comparison_nomean[grep("lag2", variable), ]$akaike_weight)
lags_RVI_scaled[4,3] <- sum(departure_model_comparison_nomean[grep("lag3", variable), ]$akaike_weight)
lags_RVI_scaled[5,3] <- sum(departure_model_comparison_nomean[grep("lag4", variable), ]$akaike_weight)
lags_RVI_scaled[6,3] <- sum(departure_model_comparison_nomean[grep("lag5", variable), ]$akaike_weight)
lags_RVI_scaled[7,3] <- sum(departure_model_comparison_nomean[grep("lag6", variable), ]$akaike_weight)
lags_RVI_scaled[8,3] <- sum(departure_model_comparison_nomean[grep("lag7", variable), ]$akaike_weight)
lags_RVI_scaled[9,3] <- sum(departure_model_comparison_nomean[grep("lag8", variable), ]$akaike_weight)
lags_RVI_scaled[10,3] <- sum(departure_model_comparison_nomean[grep("lag9", variable), ]$akaike_weight)

saveRDS(lags_RVI_scaled, here("Model_results","lags_RVI_scaled.rds"))

#visualize lags through time
ggplot(data = lags_RVI_scaled, aes(x = arrival_lag)) +
  geom_line(aes(y = arrival_RVI), ) +
  geom_line(aes(y = departure_RVI), linetype = "dashed") +
  labs(x = "Lag (years)", y = "Relative Variable Importance") +
  scale_color_discrete() + #how to make a legend
  theme_classic() +
  theme(text = element_text(size = 20)) +
  scale_x_continuous(breaks = c(0:9))

Table for RVI data for arrival

arrival_departure <- c("arrival","arrival","arrival","arrival","arrival", "arrival","arrival", "arrival", "arrival","arrival","arrival","arrival","arrival","arrival", "arrival","arrival", "arrival", "arrival","arrival")
type <- c("Depth", "Depth", "lag", "lag", "Transformation", "Transformation", "Transformation", "Metric", "Metric", "Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric")
variable <- c("Bottom", "Surface", "no_lag", "lagged", "|Change|", "Change", "Raw", "Min", "Max", "Seas", "Raw x Min", "Raw x Max", "Raw x Seas", "Change x Min", "Change x Max", "Change x Seas", "|Change| x Min", "|Change| x Max", "|Change| x Seas")


value <- c(arrival_bottom_importance, arrival_surface_importance, arrival_nolag_importance, arrival_lag_importance, arrival_abs_importance, arrival_change_importance, arrival_raw_importance, arrival_min_temp_importance, arrival_max_temp_importance, arrival_seas_temp_importance, arrival_raw_min_importance, arrival_raw_max_importance, arrival_raw_seas_importance, arrival_change_min_importance, arrival_change_max_importance, arrival_change_seas_importance, arrival_abs_change_min_importance, arrival_abs_change_max_importance, arrival_abs_change_seas_importance)

RVI_arrival <- data.table(arrival_departure, type, variable, value)

Table for RVI data for departure

arrival_departure <- c("departure","departure","departure","departure","departure", "departure","departure", "departure", "departure","departure","departure","departure","departure","departure", "departure","departure", "departure", "departure","departure")
type <- c("Depth", "Depth", "lag", "lag", "Transformation", "Transformation", "Transformation", "Metric", "Metric", "Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric", "Transformation x Metric")
variable <- c("Bottom", "Surface", "no_lag", "lagged", "|Change|", "Change", "Raw", "Min", "Max", "Seas", "Raw x Min", "Raw x Max", "Raw x Seas", "Change x Min", "Change x Max", "Change x Seas", "|Change| x Min", "|Change| x Max", "|Change| x Seas")
value <- c(departure_bottom_importance, departure_surface_importance, departure_nolag_importance, departure_lag_importance, departure_abs_importance, departure_change_importance, departure_raw_importance, departure_min_temp_importance, departure_max_temp_importance, departure_seas_temp_importance, departure_raw_min_importance, departure_raw_max_importance, departure_raw_seas_importance, departure_change_min_importance, departure_change_max_importance, departure_change_seas_importance, departure_abs_change_min_importance, departure_abs_change_max_importance, departure_abs_change_seas_importance)

RVI_departure <- data.table(arrival_departure, type, variable, value)

Merge RVI tables for arrival and departure, and then graph

RVI_table <- as.data.table(rbind(RVI_arrival, RVI_departure)) #bind RVI for arrivals and departures

RVI_table.r <- RVI_table[!grep("Surface", variable)][!grep("lagged", variable)]

#change order of factor levels
RVI_table.r[, variable := factor(variable, levels = c("Bottom", "no_lag", "Raw", "Change", "|Change|", "Min", "Max", "Seas"))]

saveRDS(RVI_table, file = here("Model_results", "RVI_table.rds"))

ggplot(data = RVI_table.r, aes(x=variable, y = value, fill = arrival_departure)) +
  geom_bar(stat = "identity", position = "dodge") +
  scale_x_discrete(breaks = c("Bottom", "no_lag", "Raw", "Change", "|Change|", "Min", "Max", "Seas"), 
                   labels = c("Bottom Temp", "No Lag", "Raw Temp", "Change in \nTemp", "| Change in\n Temp |", "Min Temp", "Max Temp", "Seas")) +
  labs(x = "Temperature Variables", y = "Relative Variable Importance")  +
  theme_bw()

Another way to visualize is stacked bar plot.

#put levels into correct order for viewing, and add dummy level for legend
RVI_arrival[, variable := factor(variable, levels = c("Bottom", "Surface","  ", "Raw", "Change", "|Change|","", "no_lag", "lagged", "Min", "Max", "Seas"))]
RVI_arrival[, type := factor(type, levels = c("Depth", "Transformation", "Metric", "lag"))]

RVI_arrival_nolag <- RVI_arrival[type != "lag",]
RVI_arrival_nolag[, type := factor(type, levels = c("Depth", "Transformation", "Metric"))][, variable := factor(variable, levels = c("Bottom", "Surface","  ", "Raw", "Change", "|Change|","", "Min", "Max", "Seas"))]

saveRDS(RVI_arrival_nolag, here("Model_results", "RVI_arrival_nolag.rds"))

#and again for departure
RVI_departure[, variable := factor(variable, levels = c("Bottom", "Surface","  ", "Raw", "Change", "|Change|","", "no_lag", "lagged", "Min", "Max", "Seas"))]
RVI_departure[, type := factor(type, levels = c("Depth", "Transformation", "Metric", "lag"))]

RVI_departure_nolag <- RVI_departure[type != "lag",]
RVI_departure_nolag[, type := factor(type, levels = c("Depth", "Transformation", "Metric"))][, variable := factor(variable, levels = c("Bottom", "Surface","  ", "Raw", "Change", "|Change|","", "Min", "Max", "Seas"))]

saveRDS(RVI_departure_nolag, here("Model_results", "RVI_departure_nolag.rds"))


#plotting
pal <- wes_palette("GrandBudapest1", 8, type = "continuous")
colors <- c(pal[1], pal[2], "#FFFFFF", pal[3], pal[4], pal[5],"#FFFFFF", pal[6], pal[7], pal[8])

#arrivals
RVI_arrival_plot <- ggplot(data = RVI_arrival_nolag, aes(x=type, y = value, fill = variable)) +
  geom_bar(stat="identity", color = "black", size = 0, width = 0.8) +
  scale_x_discrete(breaks = c("Depth", "Transformation", "Metric"), labels = c("Depth", "Transformation", "Metric")) +
  labs(x = "Temperature Variables", y = "Relative Variable Importance") +
  theme_classic() +
  theme(text = element_text(size = 11.5), 
        legend.position = "right", 
        legend.title = element_blank(), 
        legend.spacing.x = unit(0.2, 'cm'),
        legend.justification = "center",
        aspect.ratio = (1),
        #, legend.position = "none"
        ) +
  guides(fill=guide_legend(ncol=1)) +
  scale_fill_manual(values = colors,
                    drop = F)

#departure
RVI_departure_plot <- ggplot(data = RVI_departure_nolag, aes(x=type, y = value, fill = variable)) +
  geom_bar(stat="identity", color = "black", size = 0, width = 0.8) +
  scale_x_discrete(breaks = c("Depth", "Transformation", "Metric"), labels = c("Depth", "Transformation", "Metric")) +
  labs(x = "Temperature Variables", y = "Relative Variable Importance") +
  theme_classic() +
  theme(text = element_text(size = 11.5), 
        legend.position = "right", 
        legend.title = element_blank(), 
        legend.spacing.x = unit(0.2, 'cm'),
        legend.justification = "center",
        aspect.ratio = (1),
        #, legend.position = "none"
        ) +
  guides(fill=guide_legend(ncol=1)) +
  scale_fill_manual(values = colors,
                    drop = F)

RVI_table
RVI_arrival_plot
RVI_departure_plot

Next step is to add the coefficients on to the bar chart. To do this, I will need to sum (aikake weight of model including variable x coefficient). I think this will be easy enough Using arrival_model_comparison_nomean data frame. I will add new column to data frame of aikaike weight x coefficient

#for some reason the coefficient is a factor
arrival_model_comparison_nomean[,coef_num := as.numeric(as.character(coef))]
arrival_model_comparison_nomean[,aw_coef := akaike_weight * coef_num]

#bottom temperature avg coefficient
arrival_bottom_temp_avg_coef <- sum(arrival_model_comparison_nomean[grep("sbt", variable)]$coef_num)

#surface temperature avg coefficient
arrival_surface_temp_avg_coef <- sum(arrival_model_comparison_nomean[grep("sst", variable)]$coef_num)

#raw seasonality avg coefficient
arrival_seas_raw_avg_coef <- 
  sum(arrival_model_comparison_nomean[grep("seas", variable), ][!grep("change", variable)]$coef_num)

#max abs change avg coefficient
arrival_max_abs_change_avg_coef <- 
  sum(arrival_model_comparison_nomean[grep("max_s.t_temp_change_abs", variable), ]$coef_num)
#for some reason the coefficient is a factor
departure_model_comparison_nomean[,coef_num := as.numeric(as.character(coef))]
departure_model_comparison_nomean[,aw_coef := akaike_weight * coef_num]

#bottom temperature avg coefficient
departure_bottom_temp_avg_coef <- sum(departure_model_comparison_nomean[grep("sbt", variable)]$coef_num)

#surface temperature avg coefficient
departure_surface_temp_avg_coef <- sum(departure_model_comparison_nomean[grep("sst", variable)]$coef_num)

#raw seasonality avg coefficient
departure_seas_raw_avg_coef <- 
  sum(departure_model_comparison_nomean[grep("seas", variable), ][!grep("change", variable)]$coef_num)

#min change avg coefficient
departure_min_abs_change_avg_coef <- 
  sum(departure_model_comparison_nomean[grep("min_s.t_temp_change", variable), ][!grep("abs", variable)]$coef_num)

#seas change avg coefficient
departure_seas_change_avg_coef <- 
  sum(departure_model_comparison_nomean[grep("seas_s.t_temp_change", variable), ][!grep("abs", variable)]$coef_num)




(These analyses were irrelevant and therefore not repeated for revisions) ##What if we run these models with fish only? No traits? How do inverts change the story? Because it looks like above, not a ton of invertebrates are going in and out.

#list of fish names from trait database
traits <- fread("TraitCollectionFishNAtlanticNEPacificContShelf (3).csv")

#make fish no fish key
fish <- data.table(spp = unique(traits$taxon), fish = "Y")

#combine with spp master
spp_master_ztemp_seus_buoy_scaled_fishonly <- merge(spp_master_ztemp_seus_buoy_scaled, fish, all.x = T)

#get rid of any rows that aren't observations of fish
spp_master_ztemp_seus_buoy_scaled_fishonly2 <- spp_master_ztemp_seus_buoy_scaled_fishonly[fish == "Y",]

Running models for fish only


#names of scaled columns
scaled_cols <- grep("*_scaled", names(spp_master_ztemp_seus_buoy_scaled_fishonly2), value = T)

#going to make loop to make all models I need to look at with single variables
variables_scaled <- colnames(spp_master_ztemp_seus_buoy_scaled_fishonly2[,scaled_cols, with = FALSE])

arrival_model_comparison_spprandom_scaled_seus_update_fishonly <- as.data.table(matrix(nrow = length(variables_scaled)))
arrival_model_comparison_spprandom_scaled_seus_update_fishonly[, variable:=as.factor(V1)][, coef:=as.numeric(V1)][, p_value:=as.numeric(V1)][, AICc:=as.numeric(V1)]
arrival_model_comparison_spprandom_scaled_seus_update_fishonly[, V1 := NULL]

for (i in 1:length(variables_scaled)){
  mod <- glmer(col ~ get(variables_scaled[i]) + (1|reg) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled_fishonly2, nAGQ = 0)
  arrival_model_comparison_spprandom_scaled_seus_update_fishonly[i,variable := variables_scaled[i]]
  arrival_model_comparison_spprandom_scaled_seus_update_fishonly[i,coef := coef(summary(mod))[,"Estimate"][2]]
  arrival_model_comparison_spprandom_scaled_seus_update_fishonly[i,p_value := coef(summary(mod))[,"Pr(>|z|)"][2]]
  arrival_model_comparison_spprandom_scaled_seus_update_fishonly[i,AICc := AICc(mod)]
  
  print(paste(i, length(variables_scaled), sep = "/"))
    
}

#by setting nACQ to 0, all models converged

departure Models without Traits

#see setup above

departure_model_comparison_spprandom_scaled_seus_update_fishonly <- as.data.table(matrix(nrow = length(variables_scaled)))
departure_model_comparison_spprandom_scaled_seus_update_fishonly[, variable:=as.factor(V1)][, coef:=as.numeric(V1)][, p_value:=as.numeric(V1)][, AICc:=as.numeric(V1)]
departure_model_comparison_spprandom_scaled_seus_update_fishonly[, V1 := NULL]

for (i in 1:length(variables_scaled)){
  mod <- glmer(now_ext ~ get(variables_scaled[i]) + (1|reg) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled_fishonly2, nAGQ = 0)
  departure_model_comparison_spprandom_scaled_seus_update_fishonly[i,variable := variables_scaled[i]]
  departure_model_comparison_spprandom_scaled_seus_update_fishonly[i,coef := coef(summary(mod))[,"Estimate"][2]]
  departure_model_comparison_spprandom_scaled_seus_update_fishonly[i,p_value := coef(summary(mod))[,"Pr(>|z|)"][2]]
  departure_model_comparison_spprandom_scaled_seus_update_fishonly[i,AICc := AICc(mod)]
  
  print(paste(i, length(variables_scaled), sep = "/"))
    
}

#by setting nACQ to 0, all models converged

Relative Variable Importance

arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean <- arrival_model_comparison_spprandom_scaled_seus_update_fishonly[!grepl("mean",variable),]

departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean <- departure_model_comparison_spprandom_scaled_seus_update_fishonly[!grepl("mean",variable),]

#comparison to null
col_mod_null <- glmer(col ~ (1|reg) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled_fishonly2, nAGQ = 0)
AICc(col_mod_null)-min(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean$AICc)

ext_mod_null <- glmer(ext ~ (1|reg) + (1|spp), family = binomial, data = spp_master_ztemp_seus_buoy_scaled_fishonly2, nAGQ = 0)
AICc(ext_mod_null)-min(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean$AICc)

Relative Variable Importance for arrival Models

#add ∆AIC to tables
min_col_AICc_fishonly <- min(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[, AICc])
arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[,"deltaAICc" := (AICc - min_col_AICc_fishonly)]

#add relative likelihood exp( -0.5 * ∆AIC score for that model)
arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[,"rel_likelihood" := exp((-0.5 * deltaAICc))]
#sum relative likelihoods across all models
arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean.likelihoodsum <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[, rel_likelihood])
#Akaike weight for a model is this rel_likelihood devided by the sum of these values across all models
arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[,"akaike_weight" := rel_likelihood/arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean.likelihoodsum]

#I want to look at relative importance FOR 
#bottom/surface (bottom = includes sbt, grepl("sbt", variable))
col_bottom_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("sbt", variable), ]$akaike_weight)
col_surface_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("sst", variable), ]$akaike_weight)

#lag/not lagged (grepl("lag", variable))
col_lag_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag", variable), ]$akaike_weight)
col_nolag_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[!grep("lag", variable), ]$akaike_weight)

#absolute (grepl("abs", variable))
col_abs_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("abs", variable), ]$akaike_weight)

#raw (!grepl("change"))
col_raw_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[!grep("change", variable), ]$akaike_weight)

#change (grepl("change", variable), (!grepl("abs")))
col_change_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("change", variable), ][!grep("abs", variable),]$akaike_weight)

#type of temp variable (max, min, seas)
col_max_temp_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("max", variable), ]$akaike_weight)
col_min_temp_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("min", variable), ]$akaike_weight)
col_seas_temp_importance_fishonly <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("seas", variable), ]$akaike_weight)

Relative Variable Importance for departure Models

#add ∆AIC to tables
min_ext_AICc_fishonly <- min(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[, AICc])
departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[,"deltaAICc" := (AICc - min_ext_AICc_fishonly)]

#add relative likelihood exp( -0.5 * ∆AIC score for that model)
departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[,"rel_likelihood" := exp((-0.5 * deltaAICc))]
#sum relative likelihoods across all models
departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean.likelihoodsum <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[, rel_likelihood])
#Akaike weight for a model is this rel_likelihood devided by the sum of these values across all models
departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[,"akaike_weight" := rel_likelihood/departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean.likelihoodsum]

#I want to look at relative importance FOR 
#bottom/surface (bottom = includes sbt, grepl("sbt", variable))
ext_bottom_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("sbt", variable), ]$akaike_weight)
ext_surface_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("sst", variable), ]$akaike_weight)

#lag/not lagged (grepl("lag", variable))
ext_lag_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag", variable), ]$akaike_weight)
ext_nolag_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[!grep("lag", variable), ]$akaike_weight)

#absolute (grepl("abs", variable))
ext_abs_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("abs", variable), ]$akaike_weight)

#raw (!grepl("change"))
ext_raw_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[!grep("change", variable), ]$akaike_weight)

#change (grepl("change", variable), (!grepl("abs")))
ext_change_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("change", variable), ][!grep("abs", variable),]$akaike_weight)

#type of temp variable (max, min, seas)
ext_max_temp_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("max", variable), ]$akaike_weight)
ext_min_temp_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("min", variable), ]$akaike_weight)
ext_seas_temp_importance_fishonly <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("seas", variable), ]$akaike_weight)

Let’s see how the RVI importance varies by looking at specific lag values

#first, table for lags
lags_v_RVI_spprandom_scaled_fishonly <- data.table(col_lag = c(0:9), col_RVI = 0, departure_RVI = 0)
#arrival
lags_v_RVI_spprandom_scaled_fishonly[1,2] <- 1-sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[2,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag1", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[3,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag2", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[4,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag3", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[5,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag4", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[6,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag5", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[7,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag6", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[8,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag7", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[9,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag8", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[10,2] <- sum(arrival_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag9", variable), ]$akaike_weight)
#departure
lags_v_RVI_spprandom_scaled_fishonly[1,3] <- 1-sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[2,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag1", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[3,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag2", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[4,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag3", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[5,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag4", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[6,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag5", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[7,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag6", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[8,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag7", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[9,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag8", variable), ]$akaike_weight)
lags_v_RVI_spprandom_scaled_fishonly[10,3] <- sum(departure_model_comparison_spprandom_scaled_seus_update_fishonly_nomean[grep("lag9", variable), ]$akaike_weight)

ggplot(data = lags_v_RVI_spprandom_scaled_fishonly, aes(x = col_lag)) +
  geom_line(aes(y = col_RVI), col = "blue") +
  geom_line(aes(y = departure_RVI), col = "red") +
  labs(x = "Lag", y = "Relative Variable Importance") +
  scale_color_discrete() + #how to make a legend
  theme_bw()

Table for RVI data for arrival

col_ext <- c("col","col","col","col","col", "col","col", "col", "col","col")
type <- c("depth", "depth", "lag", "lag", "Change?", "Change?", "Change?", "Temp", "Temp", "Temp")
variable <- c("bottom", "surface", "no_lag", "lagged", "absolute_value_change", "change", "raw", "Min", "Max", "Seas")
value <- c(col_bottom_importance_fishonly, col_surface_importance_fishonly, col_nolag_importance_fishonly, col_lag_importance_fishonly, col_abs_importance_fishonly, col_change_importance_fishonly, col_raw_importance_fishonly, col_min_temp_importance_fishonly, col_max_temp_importance_fishonly, col_seas_temp_importance_fishonly)

RVI_col_fishonly <- data.table(col_ext, type, variable, value)

Table for RVI data for departure

col_ext <- c("ext","ext","ext","ext","ext", "ext", "ext", "ext", "ext", "ext")
type <- c("depth", "depth", "lag", "lag", "Change?", "Change?", "Change?", "Temp", "Temp", "Temp")
variable <- c("bottom", "surface", "no_lag", "lagged", "absolute_value_change", "change", "raw", "Min", "Max", "Seas")
value <- c(ext_bottom_importance_fishonly, ext_surface_importance_fishonly, ext_nolag_importance_fishonly, ext_lag_importance_fishonly, ext_abs_importance_fishonly, ext_change_importance_fishonly, ext_raw_importance_fishonly, ext_min_temp_importance_fishonly, ext_max_temp_importance_fishonly, ext_seas_temp_importance_fishonly)

RVI_ext_fishonly <- data.table(col_ext, type, variable, value)

Merge RVI tables for arrival and departure, and then graph

RVI_table_fishonly <- as.data.table(rbind(RVI_col_fishonly, RVI_ext_fishonly)) #bind RVI for arrivals and departures

RVI_table.r_fishonly <- RVI_table_fishonly[!grep("surface", variable)][!grep("lagged", variable)]

#change order of factor levels
RVI_table.r_fishonly[, variable := factor(variable, levels = c("bottom", "no_lag", "raw", "change", "absolute_value_change", "Min", "Max", "Seas"))]

save(RVI_table_fishonly, file = "RVI_table_fishonly.Rdata")

ggplot(data = RVI_table.r_fishonly, aes(x=variable, y = value, fill = col_ext)) +
  geom_bar(stat = "identity", position = "dodge") +
  scale_x_discrete(breaks = c("bottom", "no_lag", "raw", "change", "absolute_value_change", "Min", "Max", "Seas"), labels = c("Bottom Temp", "No Lag", "Raw Temp", "Change in \nTemp", "| Change in\n Temp |", "Min Temp", "Max Temp", "Seas")) +
  labs(x = "Temperature Variables", y = "Relative Variable Importance")  +
  theme_bw()

Another way to visualize is stacked bar plot.

#put levels into correct order for viewing
RVI_table_fishonly[, variable := factor(variable, levels = c("bottom", "surface", "absolute_value_change", "change", "raw", "no_lag", "lagged", "Min", "Max", "Seas"))]
#make types factors as well
RVI_table_fishonly[,type := as.factor(type)]

#arrival
RVI_col_plot_fishonly <- ggplot(data = RVI_table_fishonly[col_ext == "col",], aes(x=type, y = value, fill = variable)) +
  geom_bar(stat="identity", color = "black") +
  scale_x_discrete(breaks = c("Change?", "depth", "lag", "Temp"), labels = c("Change in\ntemp?", "Metric\nDepth", "Lagged?", "Temp")) +
  labs(x = "Temperature Variables", y = "Relative Variable Importance") +
  theme_classic() +
  theme(text = element_text(size = 22)
        #, legend.position = "none"
        )

#departure
RVI_ext_plot_fishonly <- ggplot(data = RVI_table_fishonly[col_ext == "ext",], aes(x=type, y = value, fill = variable)) +
  geom_bar(stat="identity", color = "black") +
  scale_x_discrete(breaks = c("Change?", "depth", "lag", "Temp"), labels = c("Change in\ntemp?", "Metric\nDepth", "Lagged?", "Temp")) +
  labs(x = "Temperature Variables", y = "Relative Variable Importance") +
  theme_classic()  +
  theme(text = element_text(size = 22)
        #, legend.position = "none"
        )

RVI_table_fishonly
RVI_col_plot_fishonly
RVI_ext_plot_fishonly
LS0tCnRpdGxlOiAiQXJyaXZhbCBhbmQgRGVwYXJ0dXJlIEZpbmFsIE1vZGVscyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhIGNsZWFuZWQgdmVyc2lvbiBvZiAwNF8yNF8xOSBUZW1wIGxpbmsgdHJhaXQgZmlzaC5SbWQvMTFfMjBfMTlfVGVtcF9saW5rX3RyYWl0c19maXNoLlJtZC4KQ2hhbmdlcwoqIGltcHJvdmVkIGZvcm1hdHRpbmcKKiBlYXNpZXIgdG8gZm9sbG93Ciogc3BlY2llcyBhbmQgcmVnaW9uIGFzIHJhbmRvbSBlZmZlY3RzCiogc2NhbGluZyB0ZW1wZXJhdHVyZSB2YWx1ZXMKKiBzZXR0aW5nIG5BQ1EgdG8gMCwgc2VlIHdoeSAgW2hlcmVdKGh0dHBzOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzc3MzEzL3doeS1jYW50LWktbWF0Y2gtZ2xtbVRNQi1mYW1pbHktYmlub21pYWwtb3V0cHV0LXdpdGgtbWFudWFsLWltcGxlbWVudGF0aW9uLW9mLWcpLiAKCkF1Z3VzdCAxMSwgMjAyMjogV29ya2luZyBvbiBSZXZpc2lvbnMgZnJvbSBHbG9iYWwgRWNvbG9neSBhbmQgQmlvZ2VvZ3JhcGh5CiogQWRkIHJhbmRvbSBlZmZlY3RzIGZvciBvcmRlciwgZ2VudXMsIGZhbWlseSwgZXRjLgoKYGBge3Igc2V0dXB9CmxpYnJhcnkoTXVNSW4pCmxpYnJhcnkobG1lNCkKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoaGVyZSkKbGlicmFyeSh3ZXNhbmRlcnNvbikgIyB0byBjb2xvciBwbG90cwpsaWJyYXJ5KHRheGl6ZSkgI3RvIG9idGFpbiBvcmRlciwgZ2VudXMsIGZhbWlseQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KERIQVJNYSkKCnNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZCA8LSByZWFkUkRTKGhlcmUoIkRhdGEiLCJTcHBfbWFzdGVyIiwgInNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZC5yZHMiKSkKYGBgCgpMaW5rIHVwIHdpdGggc3BwIGtleSB0byBhZGQgcGh5bHVtLCBvcmRlciwgZmFtaWx5LCBldGMuCmBgYHtyIHB1bGwgaW4gc3BwLCBvcmRlciwgZmFtaWx5LCBldGMufQpzcHBfa2V5IDwtIGZyZWFkKGhlcmU6OmhlcmUoIkRhdGEiLCJTcHBfbWFzdGVyIiwic3BwX2tleS5jc3YiKSkKCnNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZCA8LSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWRbc3BwX2tleSwgb24gPSAic3BwIl0KCiAgICAKYGBgCgoKUnVubmluZywgYW5kIHJhbmtpbmcgYXJyaXZhbCBtb2RlbHMgd2l0aG91dCB0cmFpdHMKCiMjSGVyZSwgSSBzY2FsZWQgYWxsIHRlbXBlcmF0dXJlIHZhbHVlcyBhY3Jvc3MgYWxsIHJlZ2lvbnMsIGFuZCBpbmNsdWRlZCBzcGVjaWVzIGFzIGEgcmFuZG9tIGVmZmVjdC4gSW4gb3JkZXIgdG8gZG8gdGhpcywgSSBoYWQgdG8gY2hhbmdlIHRoZSBhbGdvcml0aG0gc2xpZ2h0bHktLW5BR1EgPSAwLgoKR2Fpbi9BcnJpdmFsIE1vZGVscyB3aXRoIEFkZGl0aW9uYWwgcmFuZG9tIGVmZmVjdHMKCmBgYHtyIGFycml2YWwgbW9kZWxzIHdpdGhvdXQgdHJhaXRzIGFkZGl0aW9uYWwgcmFuZG9tIGVmZmVjdHMgZm9yIHBoeWxvZ2VueSB9CiNuYW1lcyBvZiBzY2FsZWQgY29sdW1ucwp2YXJpYWJsZXNfc2NhbGVkIDwtIGdyZXAoIipfc2NhbGVkIiwgbmFtZXMoc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkKSwgdmFsdWUgPSBUKQojZ29pbmcgdG8gbWFrZSBsb29wIHRvIG1ha2UgYWxsIG1vZGVscyBJIG5lZWQgdG8gbG9vayBhdCB3aXRoIGEgc2luZ2xlIHRlbXBlcmF0dXJlIHZhcmlhYmxlCgphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fdGF4b25vbXkgPC0gYXMuZGF0YS50YWJsZShtYXRyaXgobnJvdyA9IGxlbmd0aCh2YXJpYWJsZXNfc2NhbGVkKSkpCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVssIHZhcmlhYmxlOj1hcy5mYWN0b3IoVjEpXVssIGNvZWY6PWFzLm51bWVyaWMoVjEpXVssIHBfdmFsdWU6PWFzLm51bWVyaWMoVjEpXVssIEFJQ2M6PWFzLm51bWVyaWMoVjEpXQphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fdGF4b25vbXlbLCBWMSA6PSBOVUxMXQoKZm9yIChpIGluIDE6bGVuZ3RoKHZhcmlhYmxlc19zY2FsZWQpKXsKICBtb2QgPC0gZ2xtZXIoY29sIH4gZ2V0KHZhcmlhYmxlc19zY2FsZWRbaV0pICsgKDF8cmVnKSArICgxfHBoeWx1bSkgKyAoMXxjbGFzcykgKyAoMXxvcmRlcikgKyAoMXxmYW1pbHkpICsgKDF8Z2VudXMpICsgKDF8c3BwKSwKICAgICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQsIG5BR1EgPSAwKQogIGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVtpLHZhcmlhYmxlIDo9IHZhcmlhYmxlc19zY2FsZWRbaV1dCiAgYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3RheG9ub215W2ksY29lZiA6PSBjb2VmKHN1bW1hcnkobW9kKSlbLCJFc3RpbWF0ZSJdWzJdXQogIGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVtpLHBfdmFsdWUgOj0gY29lZihzdW1tYXJ5KG1vZCkpWywiUHIoPnx6fCkiXVsyXV0KICBhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fdGF4b25vbXlbaSxBSUNjIDo9IEFJQ2MobW9kKV0KICAKICBwcmludChwYXN0ZShpLCBsZW5ndGgodmFyaWFibGVzX3NjYWxlZCksIHNlcCA9ICIvIikpCiAgICAKfQoKI2J5IHNldHRpbmcgbkFDUSB0byAwLCBhbGwgbW9kZWxzIGNvbnZlcmdlZAoKc2F2ZVJEUyhvYmplY3QgPSBhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fdGF4b25vbXksIGZpbGUgPSBoZXJlKCJNb2RlbF9yZXN1bHRzIiwiYXJyaXZhbF9tb2RlbF9yZXN1bHRzX3RheG9ub215LnJkcyIpKQpmd3JpdGUoYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3RheG9ub215LCBmaWxlID0gaGVyZSgiTW9kZWxfcmVzdWx0cyIsImFycml2YWxfbW9kZWxfcmVzdWx0c190YXhvbm9teS5jc3YiKSkKYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3RheG9ub215IDwtIHJlYWRSRFMoaGVyZTo6aGVyZSgiTW9kZWxfcmVzdWx0cyIsImFycml2YWxfbW9kZWxfcmVzdWx0c190YXhvbm9teS5yZHMiKSkKCmBgYAoKTW9kZWwgcGVyZm9ybWFuY2UgYW5kIGFzc3VtcHRpb25zLgpgYGB7cn0KI2xldCdzIHRha2UgYSBsb29rIGF0IGJlc3QgcGVyZm9ybWluZyBtb2RlbCwgYW5kIGNoZWNrIGFzc3VtcHRpb25zCm1vZF9leHRyYXJhbmRvbV9nYWluIDwtIGdsbWVyKGNvbCB+IHNlYXNfc3N0X3RlbXBfc2NhbGVkICArICgxfHJlZykgKyAoMXxwaHlsdW0pICsgKDF8Y2xhc3MpICsgKDF8b3JkZXIpICsgKDF8ZmFtaWx5KSArICgxfGdlbnVzKSArICgxfHNwcCksIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkLCBuQUdRID0gMCkKCiNQZXJmb3JtYW5jZQojUi1TcXVhcmVkCnIuc3F1YXJlZEdMTU0obW9kX2V4dHJhcmFuZG9tX2dhaW4pCgojdGhlb3JldGljYWwgdmFyaWFuY2U6CiAgI3RoZSB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIGZpeGVkIGVmZmVjdHM6IDAuMDQKICAjYSB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIGVudGlyZSBtb2RlbCwgaW5jbHVkaW5nIGJvdGggZml4ZWQgYW5kIHJhbmRvbSBlZmZlY3RzOiAwLjQ0CgojZGVsdGEgKG9ic2VydmF0aW9uYWwpIHZhcmlhbmNlOgogICN0aGUgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IHRoZSBmaXhlZCBlZmZlY3RzOiAwLjAxNQogICNhIHZhcmlhbmNlIGV4cGxhaW5lZCBieSB0aGUgZW50aXJlIG1vZGVsLCBpbmNsdWRpbmcgYm90aCBmaXhlZCBhbmQgcmFuZG9tIGVmZmVjdHM6IDAuMTYKCiNjb2VmID0gIC0wLjQ5CiNob3cgbXVjaCB0aGUgcHJvYmFiaWxpdHkgY2hhbmdlcyB3aXRoIGEgZ2l2ZW4gY2hhbmdlIGluIHRlbXBlcmF0dXJlCnNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZC5yIDwtIHNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZFtjb21wbGV0ZS5jYXNlcyhzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWRbICwgLihzZWFzX3NzdF90ZW1wX3NjYWxlZCwgY29sLCByZWcsIHBoeWx1bSwgY2xhc3MsIG9yZGVyLCBmYW1pbHksIGdlbnVzLCBzcHApXSksXQoKI01vZGVsIGFzc3VtcHRpb25zIHVzaW5nIERIQVJNYSBwYWNrYWdlCiNUZXN0IGZvciBvdmVyZGlzcGVyc2lvbgojZ3JvdXBpbmcgYmFzaWNhbGx5IHRyYW5zZm9ybXMgMC8xIHJlc3BvbnNlIChiZXJub3VsbGkpIGluIGEgay9uIHJlc3BvbnNlICh0cnVlIGJpbm9taWFsKQojaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0RIQVJNYS92aWduZXR0ZXMvREhBUk1hLmh0bWwjYmlub21pYWwtZGF0YQojZ3JvdXAgYnkgcmVnaW9uCnNpbXVsYXRpb25PdXRwdXQgPC0gc2ltdWxhdGVSZXNpZHVhbHMoZml0dGVkTW9kZWwgPSBtb2RfZXh0cmFyYW5kb21fZ2FpbikKc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlyZWcgPC0gcmVjYWxjdWxhdGVSZXNpZHVhbHMoc2ltdWxhdGlvbk91dHB1dCwgZ3JvdXAgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQuciRyZWcpCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRpb25PdXRwdXQpCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5cmVnKQpwbG90KHNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5cmVnKQoKI2dyb3VwIGJ5IHNwcApzaW11bGF0aW9uT3V0cHV0Lmdyb3VwZWRieXNwcCA8LSByZWNhbGN1bGF0ZVJlc2lkdWFscyhzaW11bGF0aW9uT3V0cHV0LCBncm91cCA9IHNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZC5yJHNwcCkKdGVzdERpc3BlcnNpb24oc2ltdWxhdGlvbk91dHB1dCkKdGVzdERpc3BlcnNpb24oc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlzcHApCnBsb3Qoc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlzcHApCgpgYGAKIlRoZSBlc3RpbWF0ZSBmb3Igc2Vhc29uYWxpdHkgb2YgLTAuNDkgbWVhbnMgdGhhdCBhIDEgZGVncmVlIGluY3JlYXNlIGluIHNlYXNvbmFsaXR5IGlzIGFzc29jaWF0ZWQgd2l0aCBhIDAuNDkgZGVjcmVhc2UgaW4gdGhlIGxvZy1vZGRzIG9mIGEgR2FpbiBvY2N1cmluZywgY29tcGFyZWQgdG8gbm8gR2FpbiBvY2N1cmluZy4gSWYgd2UgZXhwb25lbnRpYXRlIHRoaXMgbnVtYmVyIHRoZW4gd2Ugb2J0YWluIHRoZSBvZGRzIHJhdGlvIG9mIDAuNjEwODMwOCwgd2hpY2ggbWVhbnMgdGhhdCBmb3IgYSAxIGRlZ3JlZSBpbmNyZWFzZSBpbiBTZWFzb25hbGl0eSB3ZSBleHBlY3QgdG8gc2VlIChhcHByb3hpbWF0ZWx5KSBhIDM5JSBkZWNyZWFzZSBpbiB0aGUgb2RkcyBvZiBhIEdhaW4gT2NjdXJyaW5nLiIgRnJvbSB0aGlzIFtTdGFjayBFeGNoYW5nZSBwb3N0XShodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy80NDQ3OTcvaW50ZXJwcmV0aW5nLWEtZ2VuZXJhbGlzZWQtbGluZWFyLW1peGVkLW1vZGVsLXdpdGgtYmlub21pYWwtZGF0YSkuIAoKIyMjRGVwYXJ0dXJlIE1vZGVscyB3aXRob3V0IFRyYWl0cyBidXQgd2l0aCByYW5kb20gZWZmZWN0cyBmb3IgcGh5bG9nZW55CmBgYHtyIGRlcGFydHVyZSBtb2RlbHMgd2l0aG91dCB0cmFpdHMgd2l0aCByYW5kb20gZWZmZWN0IHBoeWxvZ2VueX0KCmRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3RheG9ub215IDwtIGFzLmRhdGEudGFibGUobWF0cml4KG5yb3cgPSBsZW5ndGgodmFyaWFibGVzX3NjYWxlZCkpKQpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVssIHZhcmlhYmxlOj1hcy5mYWN0b3IoVjEpXVssIGNvZWY6PWFzLm51bWVyaWMoVjEpXVssIHBfdmFsdWU6PWFzLm51bWVyaWMoVjEpXVssIEFJQ2M6PWFzLm51bWVyaWMoVjEpXQpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVssIFYxIDo9IE5VTExdCgpmb3IgKGkgaW4gMTpsZW5ndGgodmFyaWFibGVzX3NjYWxlZCkpewogIG1vZCA8LSBnbG1lcihub3dfZXh0IH4gZ2V0KHZhcmlhYmxlc19zY2FsZWRbaV0pICsgKDF8cmVnKSArICgxfHBoeWx1bSkgKyAoMXxjbGFzcykgKyAoMXxvcmRlcikgKyAoMXxmYW1pbHkpICsgKDF8Z2VudXMpICsgKDF8c3BwKSwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQsIG5BR1EgPSAwKQogIGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3RheG9ub215W2ksdmFyaWFibGUgOj0gdmFyaWFibGVzX3NjYWxlZFtpXV0KICBkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVtpLGNvZWYgOj0gY29lZihzdW1tYXJ5KG1vZCkpWywiRXN0aW1hdGUiXVsyXV0KICBkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVtpLHBfdmFsdWUgOj0gY29lZihzdW1tYXJ5KG1vZCkpWywiUHIoPnx6fCkiXVsyXV0KICBkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVtpLEFJQ2MgOj0gQUlDYyhtb2QpXQogIAogIHByaW50KHBhc3RlKGksIGxlbmd0aCh2YXJpYWJsZXNfc2NhbGVkKSwgc2VwID0gIi8iKSkKICAgIAp9CgoKc2F2ZVJEUyhvYmplY3QgPSBkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teSwgZmlsZSA9IGhlcmUoIk1vZGVsX3Jlc3VsdHMiLCJkZXBhcnR1cmVfbW9kZWxfcmVzdWx0c190YXhvbm9teS5yZHMiKSkKZndyaXRlKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3RheG9ub215LCBmaWxlID0gaGVyZSgiTW9kZWxfcmVzdWx0cyIsImRlcGFydHVyZV9tb2RlbF9yZXN1bHRzX3RheG9ub215LmNzdiIpKQoKZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fdGF4b25vbXkgPC0gcmVhZFJEUyhoZXJlOjpoZXJlKCJNb2RlbF9yZXN1bHRzIiwiZGVwYXJ0dXJlX21vZGVsX3Jlc3VsdHNfdGF4b25vbXkucmRzIikpCgojbGV0J3MgdGFrZSBhIGxvb2sgYXQgYmVzdCBwZXJmb3JtaW5nIG1vZGVsLCBhbmQgY2hlY2sgYXNzdW1wdGlvbnMKbW9kX2V4dHJhcmFuZG9tX2xvc3MgPC0gZ2xtZXIobm93X2V4dCB+IHNlYXNfc3N0X3RlbXBfbGFnM19zY2FsZWQgICsgKDF8cmVnKSArICgxfHBoeWx1bSkgKyAoMXxjbGFzcykgKyAoMXxvcmRlcikgKyAoMXxmYW1pbHkpICsgKDF8Z2VudXMpICsgKDF8c3BwKSwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQsIG5BR1EgPSAwKQoKI2xldCdzIGxvb2sgYXQgYmVzdCBwZXJmb3JtaW5nIG1vZGVsIHdpdGhvdXQgcmFuZG9tIGVmZmVjdHMKbW9kX2V4dHJhcmFuZG9tX2xvc3Nfbm9SRSA8LSBnbG0obm93X2V4dCB+IHNlYXNfc3N0X3RlbXBfbGFnM19zY2FsZWQsIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkKQoKI1ItU3F1YXJlZApyLnNxdWFyZWRHTE1NKG1vZF9leHRyYXJhbmRvbV9sb3NzKQoKI3RoZW9yZXRpY2FsIHZhcmlhbmNlOgogICN0aGUgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IHRoZSBmaXhlZCBlZmZlY3RzOiAwLjAxODczOTI2MgogICNhIHZhcmlhbmNlIGV4cGxhaW5lZCBieSB0aGUgZW50aXJlIG1vZGVsLCBpbmNsdWRpbmcgYm90aCBmaXhlZCBhbmQgcmFuZG9tIGVmZmVjdHM6IDAuNDUzNDgxMAoKI2RlbHRhIChvYnNlcnZhdGlvbmFsKSB2YXJpYW5jZToKICAjdGhlIHZhcmlhbmNlIGV4cGxhaW5lZCBieSB0aGUgZml4ZWQgZWZmZWN0czogMC4wMDU3NjE2MDkKICAjYSB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIGVudGlyZSBtb2RlbCwgaW5jbHVkaW5nIGJvdGggZml4ZWQgYW5kIHJhbmRvbSBlZmZlY3RzOiAwLjEzOTQyODEKCiNjb2VmID0gIC0wLjMyNDIKI2hvdyBtdWNoIHRoZSBwcm9iYWJpbGl0eSBjaGFuZ2VzIHdpdGggYSBnaXZlbiBjaGFuZ2UgaW4gdGVtcGVyYXR1cmUKCiNNb2RlbCBhc3N1bXB0aW9ucyB1c2luZyBESEFSTWEgcGFja2FnZQojVGVzdCBmb3Igb3ZlcmRpc3BlcnNpb24KI2dyb3VwaW5nIGJhc2ljYWxseSB0cmFuc2Zvcm1zIDAvMSByZXNwb25zZSAoYmVybm91bGxpKSBpbiBhIGsvbiByZXNwb25zZSAodHJ1ZSBiaW5vbWlhbCkKI2h0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ESEFSTWEvdmlnbmV0dGVzL0RIQVJNYS5odG1sI2Jpbm9taWFsLWRhdGEKI2dyb3VwIGJ5IHJlZ2lvbgpzaW11bGF0aW9uT3V0cHV0X2xvc3MgPC0gc2ltdWxhdGVSZXNpZHVhbHMoZml0dGVkTW9kZWwgPSBtb2RfZXh0cmFyYW5kb21fbG9zcykKc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlyZWdfbG9zcyA8LSByZWNhbGN1bGF0ZVJlc2lkdWFscyhzaW11bGF0aW9uT3V0cHV0X2xvc3MsIGdyb3VwID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkLnIkcmVnKQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0aW9uT3V0cHV0X2xvc3MpCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5cmVnX2xvc3MpCnBsb3Qoc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlyZWdfbG9zcykKCiNubyByYW5kb20gZWZmZWN0cwpzaW11bGF0aW9uT3V0cHV0X2xvc3Nfbm9SRSA8LSBzaW11bGF0ZVJlc2lkdWFscyhmaXR0ZWRNb2RlbCA9IG1vZF9leHRyYXJhbmRvbV9sb3NzX25vUkUpCnNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5cmVnX2xvc3Nfbm9SRSA8LSByZWNhbGN1bGF0ZVJlc2lkdWFscyhzaW11bGF0aW9uT3V0cHV0X2xvc3Nfbm9SRSwgZ3JvdXAgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQuciRyZWcpCnRlc3REaXNwZXJzaW9uKHNpbXVsYXRpb25PdXRwdXRfbG9zc19ub1JFKQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0aW9uT3V0cHV0Lmdyb3VwZWRieXJlZ19sb3NzX25vUkUpCnBsb3Qoc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlyZWdfbG9zc19ub1JFKQoKCgojZ3JvdXAgYnkgc3BwCnNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5c3BwX2xvc3MgPC0gcmVjYWxjdWxhdGVSZXNpZHVhbHMoc2ltdWxhdGlvbk91dHB1dF9sb3NzLCBncm91cCA9IHNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZC5yJHNwcCkKdGVzdERpc3BlcnNpb24oc2ltdWxhdGlvbk91dHB1dF9sb3NzKQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0aW9uT3V0cHV0Lmdyb3VwZWRieXNwcF9sb3NzKQpwbG90KHNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5c3BwX2xvc3MpCgojd2l0aCBubyByYW5kb20gZWZmZWN0cwpzaW11bGF0aW9uT3V0cHV0Lmdyb3VwZWRieXNwcF9sb3NzX25vUkUgPC0gcmVjYWxjdWxhdGVSZXNpZHVhbHMoc2ltdWxhdGlvbk91dHB1dF9sb3NzX25vUkUsIGdyb3VwID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkLnIkc3BwKQp0ZXN0RGlzcGVyc2lvbihzaW11bGF0aW9uT3V0cHV0X2xvc3Nfbm9SRSkKdGVzdERpc3BlcnNpb24oc2ltdWxhdGlvbk91dHB1dC5ncm91cGVkYnlzcHBfbG9zc19ub1JFKQpwbG90KHNpbXVsYXRpb25PdXRwdXQuZ3JvdXBlZGJ5c3BwX2xvc3Nfbm9SRSkKCmBgYAoiVGhlIGVzdGltYXRlIGZvciBzZWFzb25hbGl0eSBvZiAtMC4zMjQyIG1lYW5zIHRoYXQgYSAxIGRlZ3JlZSBpbmNyZWFzZSBpbiBzZWFzb25hbGl0eSBpcyBhc3NvY2lhdGVkIHdpdGggYSAwLjMyNDIgZGVjcmVhc2UgaW4gdGhlIGxvZy1vZGRzIG9mIGEgTG9zcyBvY2N1cmluZywgY29tcGFyZWQgdG8gbm8gTG9zcyBvY2N1cmluZy4gSWYgd2UgZXhwb25lbnRpYXRlIHRoaXMgbnVtYmVyIHRoZW4gd2Ugb2J0YWluIHRoZSBvZGRzIHJhdGlvIG9mIDAuNzIzMSwgd2hpY2ggbWVhbnMgdGhhdCBmb3IgYSAxIGRlZ3JlZSBpbmNyZWFzZSBpbiBTZWFzb25hbGl0eSB3ZSBleHBlY3QgdG8gc2VlIChhcHByb3hpbWF0ZWx5KSBhIDE4JSBkZWNyZWFzZSBpbiB0aGUgb2RkcyBvZiBhIExvc3MgT2NjdXJyaW5nLiIgRnJvbSB0aGlzIFtTdGFjayBFeGNoYW5nZSBwb3N0XShodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy80NDQ3OTcvaW50ZXJwcmV0aW5nLWEtZ2VuZXJhbGlzZWQtbGluZWFyLW1peGVkLW1vZGVsLXdpdGgtYmlub21pYWwtZGF0YSkuIAoKCgojI1JlbGF0aXZlIFZhcmlhYmxlIEltcG9ydGFuY2UKCk5COiBJIGRpZG4ndCBlbmQgdXAgdXNpbmcgbWVhbiBhcyBhIHByZWRpY3RvciB2YXJpYWJsZSAocGF0dGVybnMgY2FwdHVyZWQgaW4gbWluIGFuZCBtYXgsIGxlc3MgcmVsZXZhbnQgdG8gdGhlcm1hbCBuaWNoZSkKYGBge3IgZ2V0IHJpZCBvZiBhbnkgbW9kZWxzIHVzaW5nIG1lYW59CmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW4gPC0gYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3RheG9ub215WyFncmVwbCgibWVhbiIsdmFyaWFibGUpLF0KCmRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbiA8LSBkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl90YXhvbm9teVshZ3JlcGwoIm1lYW4iLHZhcmlhYmxlKSxdCgoKYGBgCgpIb3cgZG9lcyB0aGUgbnVsbCBtb2RlbCB3aXRoIG9ubHkgcmFuZG9tIGVmZmVjdHMgcGVyZm9ybT8KYGBge3IgbnVsbCBtb2RlbHN9CiNhZGQgbnVsbCB0byB0YWJsZXMKaW50ZXJjZXB0X2Fycml2YWxfbW9kX3NjYWxlZCA8LSBnbG1lcihjb2wgfiArICgxfHJlZykgKyAoMXxwaHlsdW0pICsgKDF8Y2xhc3MpICsgKDF8b3JkZXIpICsgKDF8ZmFtaWx5KSArICgxfGdlbnVzKSArICgxfHNwcCksIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkLCBuQUdRID0gMCkKCnIuc3F1YXJlZEdMTU0oaW50ZXJjZXB0X2Fycml2YWxfbW9kX3NjYWxlZCkKCmludGVyY2VwdF9kZXBhcnR1cmVfbW9kX3NjYWxlZCA8LSBnbG1lcihub3dfZXh0IH4gKyAoMXxyZWcpICsgKDF8cGh5bHVtKSArICgxfGNsYXNzKSArICgxfG9yZGVyKSArICgxfGZhbWlseSkgKyAoMXxnZW51cykgKyAoMXxzcHApLCBmYW1pbHkgPSBiaW5vbWlhbCwgZGF0YSA9IHNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZCwgbkFHUSA9IDApCgpyLnNxdWFyZWRHTE1NKGludGVyY2VwdF9kZXBhcnR1cmVfbW9kX3NjYWxlZCkKCiNiZXN0IG1vZGVsIGJldHRlciB0aGFuIG51bGw/IHllcwpBSUNjKGludGVyY2VwdF9hcnJpdmFsX21vZF9zY2FsZWQpLUFJQ2MobW9kX2V4dHJhcmFuZG9tX2dhaW4pCkFJQ2MoaW50ZXJjZXB0X2RlcGFydHVyZV9tb2Rfc2NhbGVkKS1BSUNjKG1vZF9leHRyYXJhbmRvbV9sb3NzKQoKCmBgYApIb3cgZG8gb3RoZXIgbG9zcyBtb2RlbHMgcGVyZm9ybSB3aXRoIEFJQ2MgbGVzcyB0aGFuIDAuMDU/CmBgYHtyfQoKbW9kX2V4dHJhcmFuZG9tX2xvc3NfMiA8LSBnbG1lcihub3dfZXh0IH4gc2Vhc19zc3RfdGVtcF9jaGFuZ2VfbGFnMl9zY2FsZWQgICsgKDF8cmVnKSArICgxfHBoeWx1bSkgKyAoMXxjbGFzcykgKyAoMXxvcmRlcikgKyAoMXxmYW1pbHkpICsgKDF8Z2VudXMpICsgKDF8c3BwKSwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQsIG5BR1EgPSAwKQpyLnNxdWFyZWRHTE1NKG1vZF9leHRyYXJhbmRvbV9sb3NzXzIpCgptb2RfZXh0cmFyYW5kb21fbG9zc18zIDwtIGdsbWVyKG5vd19leHQgfiBtaW5fc3N0X3RlbXBfY2hhbmdlX2xhZzJfc2NhbGVkICArICgxfHJlZykgKyAoMXxwaHlsdW0pICsgKDF8Y2xhc3MpICsgKDF8b3JkZXIpICsgKDF8ZmFtaWx5KSArICgxfGdlbnVzKSArICgxfHNwcCksIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkLCBuQUdRID0gMCkKci5zcXVhcmVkR0xNTShtb2RfZXh0cmFyYW5kb21fbG9zc18zKQpgYGAKCgpSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIGZvciBBcnJpdmFsIE1vZGVscwpgYGB7ciBSVkkgYXJyaXZhbHN9CiNhZGQg4oiGQUlDIHRvIHRhYmxlcwptaW5fYXJyaXZhbF9BSUNjIDwtIG1pbihhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWywgQUlDY10pCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bLCJkZWx0YUFJQ2MiIDo9IChBSUNjIC0gbWluX2Fycml2YWxfQUlDYyldCgojYWRkIHJlbGF0aXZlIGxpa2VsaWhvb2QgZXhwKCAtMC41ICog4oiGQUlDIHNjb3JlIGZvciB0aGF0IG1vZGVsKQphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWywicmVsX2xpa2VsaWhvb2QiIDo9IGV4cCgoLTAuNSAqIGRlbHRhQUlDYykpXQojc3VtIHJlbGF0aXZlIGxpa2VsaWhvb2RzIGFjcm9zcyBhbGwgbW9kZWxzCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW4ubGlrZWxpaG9vZHN1bSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhblssIHJlbF9saWtlbGlob29kXSkKI0FrYWlrZSB3ZWlnaHQgZm9yIGEgbW9kZWwgaXMgdGhpcyByZWxfbGlrZWxpaG9vZCBkaXZpZGVkIGJ5IHRoZSBzdW0gb2YgdGhlc2UgdmFsdWVzIGFjcm9zcyBhbGwgbW9kZWxzCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bLCJha2Fpa2Vfd2VpZ2h0IiA6PSByZWxfbGlrZWxpaG9vZC9hcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuLmxpa2VsaWhvb2RzdW1dCgojSSB3YW50IHRvIGxvb2sgYXQgcmVsYXRpdmUgaW1wb3J0YW5jZSBGT1I6CgojYm90dG9tL3N1cmZhY2UgKGJvdHRvbSA9IGluY2x1ZGVzIHNidCwgZ3JlcGwoInNidCIsIHZhcmlhYmxlKSkKYXJyaXZhbF9ib3R0b21faW1wb3J0YW5jZSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzYnQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKYXJyaXZhbF9zdXJmYWNlX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgic3N0IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojbGFnL25vdCBsYWdnZWQgKGdyZXBsKCJsYWciLCB2YXJpYWJsZSkpCmFycml2YWxfbGFnX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmFycml2YWxfbm9sYWdfaW1wb3J0YW5jZSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhblshZ3JlcCgibGFnIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojYWJzb2x1dGUgKGdyZXBsKCJhYnMiLCB2YXJpYWJsZSkpCmFycml2YWxfYWJzX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgiYWJzIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojcmF3ICghZ3JlcGwoImNoYW5nZSIpKQphcnJpdmFsX3Jhd19pbXBvcnRhbmNlIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWyFncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCiNjaGFuZ2UgKGdyZXBsKCJjaGFuZ2UiLCB2YXJpYWJsZSksICghZ3JlcGwoImFicyIpKSkKYXJyaXZhbF9jaGFuZ2VfaW1wb3J0YW5jZSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSksIF1bIWdyZXAoImFicyIsIHZhcmlhYmxlKSxdJGFrYWlrZV93ZWlnaHQpCgojdHlwZSBvZiB0ZW1wIHZhcmlhYmxlIChtYXgsIG1pbiwgc2VhcykKYXJyaXZhbF9tYXhfdGVtcF9pbXBvcnRhbmNlIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1heCIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQphcnJpdmFsX21pbl90ZW1wX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibWluIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmFycml2YWxfc2Vhc190ZW1wX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgic2VhcyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzIDwtIGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW4KCnNhdmVSRFMoYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzLCBmaWxlID0gaGVyZSgiTW9kZWxfcmVzdWx0cyIsImFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5fYWthaWtld2VpZ2h0cy5yZHMiKSkKc2F2ZVJEUyhhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuX2FrYWlrZXdlaWdodHMsIGZpbGUgPSBoZXJlKCJ0YWJsZXMiLCJhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuX2FrYWlrZXdlaWdodHMucmRzIikpCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5fYWthaWtld2VpZ2h0cyA8LSByZWFkUkRTKGZpbGUgPSBoZXJlKCJNb2RlbF9yZXN1bHRzIiwiYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzLnJkcyIpKQoKYGBgCgpSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIGZvciBkaWZmZXJlbnQgUGFpcnMgb2YgVHJhbnNmb3JtYXRpb24gYW5kIE1ldHJpYwpgYGB7ciBSVkkgYXJyaXZhbCBQYWlycyBUcmFuc2Zvcm1hdGlvbiBhbmQgTWV0cmljfQoKI0kgd2FudCB0byBsb29rIGF0IHJlbGF0aXZlIGltcG9ydGFuY2UgRk9SIAojbW9kZWxzIHdpdGggcmF3IGFuZCBtaW4KYXJyaXZhbF9yYXdfbWluX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibWluIiwgdmFyaWFibGUpLCBdWyFncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSldJGFrYWlrZV93ZWlnaHQpCgojbW9kZWxzIHdpdGggcmF3IGFuZCBtYXgKYXJyaXZhbF9yYXdfbWF4X2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibWF4IiwgdmFyaWFibGUpLCBdWyFncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSldJGFrYWlrZV93ZWlnaHQpCgojbW9kZWxzIHdpdGggcmF3IGFuZCBzZWFzCmFycml2YWxfcmF3X3NlYXNfaW1wb3J0YW5jZSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzZWFzIiwgdmFyaWFibGUpLCBdWyFncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSldJGFrYWlrZV93ZWlnaHQpCgoKI21vZGVscyB3aXRoIGNoYW5nZSBhbmQgbWluCmFycml2YWxfY2hhbmdlX21pbl9pbXBvcnRhbmNlIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1pbl9zLnRfdGVtcF9jaGFuZ2UiLCB2YXJpYWJsZSksIF1bIWdyZXAoImFicyIsIHZhcmlhYmxlKV0kYWthaWtlX3dlaWdodCkKCiNtb2RlbHMgd2l0aCBjaGFuZ2UgYW5kIG1heAphcnJpdmFsX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJtYXhfcy50X3RlbXBfY2hhbmdlIiwgdmFyaWFibGUpLCBdWyFncmVwKCJhYnMiLCB2YXJpYWJsZSldJGFrYWlrZV93ZWlnaHQpCgojbW9kZWxzIHdpdGggY2hhbmdlIGFuZCBzZWFzCmFycml2YWxfY2hhbmdlX3NlYXNfaW1wb3J0YW5jZSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzZWFzX3MudF90ZW1wX2NoYW5nZSIsIHZhcmlhYmxlKSwgXVshZ3JlcCgiYWJzIiwgdmFyaWFibGUpXSRha2Fpa2Vfd2VpZ2h0KQoKI21vZGVscyB3aXRoIGFicyBjaGFuZ2UgYW5kIG1pbgphcnJpdmFsX2Fic19jaGFuZ2VfbWluX2ltcG9ydGFuY2UgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibWluX3MudF90ZW1wX2NoYW5nZV9hYnMiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCiNtb2RlbHMgd2l0aCBhYnMgY2hhbmdlIGFuZCBtYXgKYXJyaXZhbF9hYnNfY2hhbmdlX21heF9pbXBvcnRhbmNlIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1heF9zLnRfdGVtcF9jaGFuZ2VfYWJzIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojbW9kZWxzIHdpdGggYWJzIGNoYW5nZSBhbmQgc2VhcwphcnJpdmFsX2Fic19jaGFuZ2Vfc2Vhc19pbXBvcnRhbmNlIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNlYXNfcy50X3RlbXBfY2hhbmdlX2FicyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKYXJyaXZhbF90cmFuc2Zvcm1fbWV0cmljX2NvbXBhcmlzb24gPC0gZGF0YS50YWJsZShUcmFuc2Zvcm1hdGlvbiA9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoInJhdyIsICJyYXciLCAicmF3IiwgImNoYW5nZSIsICJjaGFuZ2UiLCAiY2hhbmdlIiwgImFic19jaGFuZ2UiLCAiYWJzX2NoYW5nZSIsICJhYnNfY2hhbmdlIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWV0cmljID0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcChjKCJtaW4iLCAibWF4IiwgInNlYXMiKSwgMyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUlZJID0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoYXJyaXZhbF9yYXdfbWluX2ltcG9ydGFuY2UsIGFycml2YWxfcmF3X21heF9pbXBvcnRhbmNlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJpdmFsX3Jhd19zZWFzX2ltcG9ydGFuY2UsIGFycml2YWxfY2hhbmdlX21pbl9pbXBvcnRhbmNlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJpdmFsX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSwgYXJyaXZhbF9jaGFuZ2Vfc2Vhc19pbXBvcnRhbmNlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJpdmFsX2Fic19jaGFuZ2VfbWluX2ltcG9ydGFuY2UsIGFycml2YWxfYWJzX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyaXZhbF9hYnNfY2hhbmdlX3NlYXNfaW1wb3J0YW5jZSkpCgoKYGBgCgoKUmVsYXRpdmUgVmFyaWFibGUgSW1wb3J0YW5jZSBEZXBhcnR1cmUgTW9kZWxzCmBgYHtyIFJWSSBkZXBhcnR1cmV9CiNhZGQg4oiGQUlDIHRvIHRhYmxlcwptaW5fZGVwYXJ0dXJlX0FJQ2MgPC0gbWluKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhblssIEFJQ2NdKQpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bLCJkZWx0YUFJQ2MiIDo9IChBSUNjIC0gbWluX2RlcGFydHVyZV9BSUNjKV0KCiNhZGQgcmVsYXRpdmUgbGlrZWxpaG9vZCBleHAoIC0wLjUgKiDiiIZBSUMgc2NvcmUgZm9yIHRoYXQgbW9kZWwpCmRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhblssInJlbF9saWtlbGlob29kIiA6PSBleHAoKC0wLjUgKiBkZWx0YUFJQ2MpKV0KI3N1bSByZWxhdGl2ZSBsaWtlbGlob29kcyBhY3Jvc3MgYWxsIG1vZGVscwpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW4ubGlrZWxpaG9vZHN1bSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWywgcmVsX2xpa2VsaWhvb2RdKQojQWthaWtlIHdlaWdodCBmb3IgYSBtb2RlbCBpcyB0aGlzIHJlbF9saWtlbGlob29kIGRldmlkZWQgYnkgdGhlIHN1bSBvZiB0aGVzZSB2YWx1ZXMgYWNyb3NzIGFsbCBtb2RlbHMKZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWywiYWthaWtlX3dlaWdodCIgOj0gcmVsX2xpa2VsaWhvb2QvZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuLmxpa2VsaWhvb2RzdW1dCgojSSB3YW50IHRvIGxvb2sgYXQgcmVsYXRpdmUgaW1wb3J0YW5jZSBGT1IgCiNib3R0b20vc3VyZmFjZSAoYm90dG9tID0gaW5jbHVkZXMgc2J0LCBncmVwbCgic2J0IiwgdmFyaWFibGUpKQpkZXBhcnR1cmVfYm90dG9tX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzYnQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKZGVwYXJ0dXJlX3N1cmZhY2VfaW1wb3J0YW5jZSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNzdCIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI2xhZy9ub3QgbGFnZ2VkIChncmVwbCgibGFnIiwgdmFyaWFibGUpKQpkZXBhcnR1cmVfbGFnX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJsYWciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKZGVwYXJ0dXJlX25vbGFnX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhblshZ3JlcCgibGFnIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojYWJzb2x1dGUgKGdyZXBsKCJhYnMiLCB2YXJpYWJsZSkpCmRlcGFydHVyZV9hYnNfaW1wb3J0YW5jZSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImFicyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI3JhdyAoIWdyZXBsKCJjaGFuZ2UiKSkKZGVwYXJ0dXJlX3Jhd19pbXBvcnRhbmNlIDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bIWdyZXAoImNoYW5nZSIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI2NoYW5nZSAoZ3JlcGwoImNoYW5nZSIsIHZhcmlhYmxlKSwgKCFncmVwbCgiYWJzIikpKQpkZXBhcnR1cmVfY2hhbmdlX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSksIF1bIWdyZXAoImFicyIsIHZhcmlhYmxlKSxdJGFrYWlrZV93ZWlnaHQpCgojdHlwZSBvZiB0ZW1wIHZhcmlhYmxlIChtYXgsIG1pbiwgc2VhcykKZGVwYXJ0dXJlX21heF90ZW1wX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJtYXgiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKZGVwYXJ0dXJlX21pbl90ZW1wX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJtaW4iLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKZGVwYXJ0dXJlX3NlYXNfdGVtcF9pbXBvcnRhbmNlIDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgic2VhcyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuX2FrYWlrZXdlaWdodHMgPC0gZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuCgpzYXZlUkRTKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzLCBmaWxlID0gaGVyZSgiTW9kZWxfcmVzdWx0cyIsImRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzLnJkcyIpKQpzYXZlUkRTKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzLCBmaWxlID0gaGVyZSgidGFibGVzIiwiZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuX2FrYWlrZXdlaWdodHMucmRzIikpCmRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbl9ha2Fpa2V3ZWlnaHRzIDwtIHJlYWRSRFMoZmlsZSA9IGhlcmUoIk1vZGVsX3Jlc3VsdHMiLCJkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5fYWthaWtld2VpZ2h0cy5yZHMiKSkKCmBgYAoKUmVsYXRpdmUgVmFyaWFibGUgSW1wb3J0YW5jZSBmb3IgUGFpcnMgb2YgVHJhbnNmb3JtYXRpb24gYW5kIE1ldHJpYyBQcmVkaWN0aW5nIGRlcGFydHVyZXMKYGBge3IgUlZJIGRlcGFydHVyZSBQYWlycyBUcmFuc2Zvcm1hdGlvbiBhbmQgTWV0cmljfQoKI0kgd2FudCB0byBsb29rIGF0IHJlbGF0aXZlIGltcG9ydGFuY2UgRk9SIAojbW9kZWxzIHdpdGggcmF3IGFuZCBtaW4KZGVwYXJ0dXJlX3Jhd19taW5faW1wb3J0YW5jZSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1pbiIsIHZhcmlhYmxlKSwgXVshZ3JlcCgiY2hhbmdlIiwgdmFyaWFibGUpXSRha2Fpa2Vfd2VpZ2h0KQoKI21vZGVscyB3aXRoIHJhdyBhbmQgbWF4CmRlcGFydHVyZV9yYXdfbWF4X2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJtYXgiLCB2YXJpYWJsZSksIF1bIWdyZXAoImNoYW5nZSIsIHZhcmlhYmxlKV0kYWthaWtlX3dlaWdodCkKCiNtb2RlbHMgd2l0aCByYXcgYW5kIHNlYXMKZGVwYXJ0dXJlX3Jhd19zZWFzX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzZWFzIiwgdmFyaWFibGUpLCBdWyFncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSldJGFrYWlrZV93ZWlnaHQpCgoKI21vZGVscyB3aXRoIGNoYW5nZSBhbmQgbWluCmRlcGFydHVyZV9jaGFuZ2VfbWluX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJtaW5fcy50X3RlbXBfY2hhbmdlIiwgdmFyaWFibGUpLCBdWyFncmVwKCJhYnMiLCB2YXJpYWJsZSldJGFrYWlrZV93ZWlnaHQpCgojbW9kZWxzIHdpdGggY2hhbmdlIGFuZCBtYXgKZGVwYXJ0dXJlX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1heF9zLnRfdGVtcF9jaGFuZ2UiLCB2YXJpYWJsZSksIF1bIWdyZXAoImFicyIsIHZhcmlhYmxlKV0kYWthaWtlX3dlaWdodCkKCiNtb2RlbHMgd2l0aCBjaGFuZ2UgYW5kIHNlYXMKZGVwYXJ0dXJlX2NoYW5nZV9zZWFzX2ltcG9ydGFuY2UgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzZWFzX3MudF90ZW1wX2NoYW5nZSIsIHZhcmlhYmxlKSwgXVshZ3JlcCgiYWJzIiwgdmFyaWFibGUpXSRha2Fpa2Vfd2VpZ2h0KQoKI21vZGVscyB3aXRoIGFicyBjaGFuZ2UgYW5kIG1pbgpkZXBhcnR1cmVfYWJzX2NoYW5nZV9taW5faW1wb3J0YW5jZSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1pbl9zLnRfdGVtcF9jaGFuZ2VfYWJzIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojbW9kZWxzIHdpdGggYWJzIGNoYW5nZSBhbmQgbWF4CmRlcGFydHVyZV9hYnNfY2hhbmdlX21heF9pbXBvcnRhbmNlIDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibWF4X3MudF90ZW1wX2NoYW5nZV9hYnMiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCiNtb2RlbHMgd2l0aCBhYnMgY2hhbmdlIGFuZCBzZWFzCmRlcGFydHVyZV9hYnNfY2hhbmdlX3NlYXNfaW1wb3J0YW5jZSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNlYXNfcy50X3RlbXBfY2hhbmdlX2FicyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKZGVwYXJ0dXJlX3RyYW5zZm9ybV9tZXRyaWNfY29tcGFyaXNvbiA8LSBkYXRhLnRhYmxlKFRyYW5zZm9ybWF0aW9uID0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygicmF3IiwgInJhdyIsICJyYXciLCAiY2hhbmdlIiwgImNoYW5nZSIsICJjaGFuZ2UiLCAiYWJzX2NoYW5nZSIsICJhYnNfY2hhbmdlIiwgImFic19jaGFuZ2UiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNZXRyaWMgPSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKGMoIm1pbiIsICJtYXgiLCAic2VhcyIpLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSVkkgPSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhkZXBhcnR1cmVfcmF3X21pbl9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfcmF3X21heF9pbXBvcnRhbmNlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXBhcnR1cmVfcmF3X3NlYXNfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2NoYW5nZV9taW5faW1wb3J0YW5jZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwYXJ0dXJlX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2NoYW5nZV9zZWFzX2ltcG9ydGFuY2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcGFydHVyZV9hYnNfY2hhbmdlX21pbl9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfYWJzX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwYXJ0dXJlX2Fic19jaGFuZ2Vfc2Vhc19pbXBvcnRhbmNlKSkKCmBgYAoKCkxldCdzIHNlZSBob3cgdGhlIFJWSSBpbXBvcnRhbmNlIHZhcmllcyBieSBsb29raW5nIGF0IHNwZWNpZmljIGxhZyB2YWx1ZXMKYGBge3IgbWFrZSBhIHBsb3QgaGVyZSBmb3IgdmFyaWFiaWxpdHkgYWNyb3NzIGxhZyB2YWx1ZXN9CgojZmlyc3QsIHRhYmxlIGZvciBsYWdzCmxhZ3NfUlZJX3NjYWxlZCA8LSBkYXRhLnRhYmxlKGFycml2YWxfbGFnID0gYygwOjkpLCBhcnJpdmFsX1JWSSA9IDAsIGRlcGFydHVyZV9SVkkgPSAwKQoKI2Fycml2YWxzCmxhZ3NfUlZJX3NjYWxlZFsxLDJdIDwtIDEtc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3NfUlZJX3NjYWxlZFsyLDJdIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzEiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc19SVklfc2NhbGVkWzMsMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnMiIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX1JWSV9zY2FsZWRbNCwyXSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJsYWczIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3NfUlZJX3NjYWxlZFs1LDJdIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc19SVklfc2NhbGVkWzYsMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnNSIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX1JWSV9zY2FsZWRbNywyXSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJsYWc2IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3NfUlZJX3NjYWxlZFs4LDJdIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc19SVklfc2NhbGVkWzksMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnOCIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX1JWSV9zY2FsZWRbMTAsMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnOSIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI2RlcGFydHVyZXMKbGFnc19SVklfc2NhbGVkWzEsM10gPC0gMS1zdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX1JWSV9zY2FsZWRbMiwzXSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzEiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc19SVklfc2NhbGVkWzMsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJsYWcyIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3NfUlZJX3NjYWxlZFs0LDNdIDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnMyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX1JWSV9zY2FsZWRbNSwzXSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc19SVklfc2NhbGVkWzYsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJsYWc1IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3NfUlZJX3NjYWxlZFs3LDNdIDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibGFnNiIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX1JWSV9zY2FsZWRbOCwzXSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc19SVklfc2NhbGVkWzksM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJsYWc4IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3NfUlZJX3NjYWxlZFsxMCwzXSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoImxhZzkiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCnNhdmVSRFMobGFnc19SVklfc2NhbGVkLCBoZXJlKCJNb2RlbF9yZXN1bHRzIiwibGFnc19SVklfc2NhbGVkLnJkcyIpKQoKI3Zpc3VhbGl6ZSBsYWdzIHRocm91Z2ggdGltZQpnZ3Bsb3QoZGF0YSA9IGxhZ3NfUlZJX3NjYWxlZCwgYWVzKHggPSBhcnJpdmFsX2xhZykpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBhcnJpdmFsX1JWSSksICkgKwogIGdlb21fbGluZShhZXMoeSA9IGRlcGFydHVyZV9SVkkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgbGFicyh4ID0gIkxhZyAoeWVhcnMpIiwgeSA9ICJSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIikgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKCkgKyAjaG93IHRvIG1ha2UgYSBsZWdlbmQKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDA6OSkpCgpgYGAKClRhYmxlIGZvciBSVkkgZGF0YSBmb3IgYXJyaXZhbApgYGB7ciBwdXQgUlZJcyBmb3IgYXJyaXZhbCBpbnRvIGRhdGEgdGFibGV9CmFycml2YWxfZGVwYXJ0dXJlIDwtIGMoImFycml2YWwiLCJhcnJpdmFsIiwiYXJyaXZhbCIsImFycml2YWwiLCJhcnJpdmFsIiwgImFycml2YWwiLCJhcnJpdmFsIiwgImFycml2YWwiLCAiYXJyaXZhbCIsImFycml2YWwiLCJhcnJpdmFsIiwiYXJyaXZhbCIsImFycml2YWwiLCJhcnJpdmFsIiwgImFycml2YWwiLCJhcnJpdmFsIiwgImFycml2YWwiLCAiYXJyaXZhbCIsImFycml2YWwiKQp0eXBlIDwtIGMoIkRlcHRoIiwgIkRlcHRoIiwgImxhZyIsICJsYWciLCAiVHJhbnNmb3JtYXRpb24iLCAiVHJhbnNmb3JtYXRpb24iLCAiVHJhbnNmb3JtYXRpb24iLCAiTWV0cmljIiwgIk1ldHJpYyIsICJNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiKQp2YXJpYWJsZSA8LSBjKCJCb3R0b20iLCAiU3VyZmFjZSIsICJub19sYWciLCAibGFnZ2VkIiwgInxDaGFuZ2V8IiwgIkNoYW5nZSIsICJSYXciLCAiTWluIiwgIk1heCIsICJTZWFzIiwgIlJhdyB4IE1pbiIsICJSYXcgeCBNYXgiLCAiUmF3IHggU2VhcyIsICJDaGFuZ2UgeCBNaW4iLCAiQ2hhbmdlIHggTWF4IiwgIkNoYW5nZSB4IFNlYXMiLCAifENoYW5nZXwgeCBNaW4iLCAifENoYW5nZXwgeCBNYXgiLCAifENoYW5nZXwgeCBTZWFzIikKCgp2YWx1ZSA8LSBjKGFycml2YWxfYm90dG9tX2ltcG9ydGFuY2UsIGFycml2YWxfc3VyZmFjZV9pbXBvcnRhbmNlLCBhcnJpdmFsX25vbGFnX2ltcG9ydGFuY2UsIGFycml2YWxfbGFnX2ltcG9ydGFuY2UsIGFycml2YWxfYWJzX2ltcG9ydGFuY2UsIGFycml2YWxfY2hhbmdlX2ltcG9ydGFuY2UsIGFycml2YWxfcmF3X2ltcG9ydGFuY2UsIGFycml2YWxfbWluX3RlbXBfaW1wb3J0YW5jZSwgYXJyaXZhbF9tYXhfdGVtcF9pbXBvcnRhbmNlLCBhcnJpdmFsX3NlYXNfdGVtcF9pbXBvcnRhbmNlLCBhcnJpdmFsX3Jhd19taW5faW1wb3J0YW5jZSwgYXJyaXZhbF9yYXdfbWF4X2ltcG9ydGFuY2UsIGFycml2YWxfcmF3X3NlYXNfaW1wb3J0YW5jZSwgYXJyaXZhbF9jaGFuZ2VfbWluX2ltcG9ydGFuY2UsIGFycml2YWxfY2hhbmdlX21heF9pbXBvcnRhbmNlLCBhcnJpdmFsX2NoYW5nZV9zZWFzX2ltcG9ydGFuY2UsIGFycml2YWxfYWJzX2NoYW5nZV9taW5faW1wb3J0YW5jZSwgYXJyaXZhbF9hYnNfY2hhbmdlX21heF9pbXBvcnRhbmNlLCBhcnJpdmFsX2Fic19jaGFuZ2Vfc2Vhc19pbXBvcnRhbmNlKQoKUlZJX2Fycml2YWwgPC0gZGF0YS50YWJsZShhcnJpdmFsX2RlcGFydHVyZSwgdHlwZSwgdmFyaWFibGUsIHZhbHVlKQpgYGAKClRhYmxlIGZvciBSVkkgZGF0YSBmb3IgZGVwYXJ0dXJlCmBgYHtyIHB1dCBSVklzIGZvciBkZXBhcnR1cmUgaW50byBkYXRhIHRhYmxlfQphcnJpdmFsX2RlcGFydHVyZSA8LSBjKCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCAiZGVwYXJ0dXJlIiwiZGVwYXJ0dXJlIiwgImRlcGFydHVyZSIsICJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiLCAiZGVwYXJ0dXJlIiwiZGVwYXJ0dXJlIiwgImRlcGFydHVyZSIsICJkZXBhcnR1cmUiLCJkZXBhcnR1cmUiKQp0eXBlIDwtIGMoIkRlcHRoIiwgIkRlcHRoIiwgImxhZyIsICJsYWciLCAiVHJhbnNmb3JtYXRpb24iLCAiVHJhbnNmb3JtYXRpb24iLCAiVHJhbnNmb3JtYXRpb24iLCAiTWV0cmljIiwgIk1ldHJpYyIsICJNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiLCAiVHJhbnNmb3JtYXRpb24geCBNZXRyaWMiKQp2YXJpYWJsZSA8LSBjKCJCb3R0b20iLCAiU3VyZmFjZSIsICJub19sYWciLCAibGFnZ2VkIiwgInxDaGFuZ2V8IiwgIkNoYW5nZSIsICJSYXciLCAiTWluIiwgIk1heCIsICJTZWFzIiwgIlJhdyB4IE1pbiIsICJSYXcgeCBNYXgiLCAiUmF3IHggU2VhcyIsICJDaGFuZ2UgeCBNaW4iLCAiQ2hhbmdlIHggTWF4IiwgIkNoYW5nZSB4IFNlYXMiLCAifENoYW5nZXwgeCBNaW4iLCAifENoYW5nZXwgeCBNYXgiLCAifENoYW5nZXwgeCBTZWFzIikKdmFsdWUgPC0gYyhkZXBhcnR1cmVfYm90dG9tX2ltcG9ydGFuY2UsIGRlcGFydHVyZV9zdXJmYWNlX2ltcG9ydGFuY2UsIGRlcGFydHVyZV9ub2xhZ19pbXBvcnRhbmNlLCBkZXBhcnR1cmVfbGFnX2ltcG9ydGFuY2UsIGRlcGFydHVyZV9hYnNfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2NoYW5nZV9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfcmF3X2ltcG9ydGFuY2UsIGRlcGFydHVyZV9taW5fdGVtcF9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfbWF4X3RlbXBfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX3NlYXNfdGVtcF9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfcmF3X21pbl9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfcmF3X21heF9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfcmF3X3NlYXNfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2NoYW5nZV9taW5faW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2NoYW5nZV9zZWFzX2ltcG9ydGFuY2UsIGRlcGFydHVyZV9hYnNfY2hhbmdlX21pbl9pbXBvcnRhbmNlLCBkZXBhcnR1cmVfYWJzX2NoYW5nZV9tYXhfaW1wb3J0YW5jZSwgZGVwYXJ0dXJlX2Fic19jaGFuZ2Vfc2Vhc19pbXBvcnRhbmNlKQoKUlZJX2RlcGFydHVyZSA8LSBkYXRhLnRhYmxlKGFycml2YWxfZGVwYXJ0dXJlLCB0eXBlLCB2YXJpYWJsZSwgdmFsdWUpCmBgYAoKTWVyZ2UgUlZJIHRhYmxlcyBmb3IgYXJyaXZhbCBhbmQgZGVwYXJ0dXJlLCBhbmQgdGhlbiBncmFwaApgYGB7ciBtZXJnZSBSVkkgdGFibGVzIGFuZCBwbG90fQpSVklfdGFibGUgPC0gYXMuZGF0YS50YWJsZShyYmluZChSVklfYXJyaXZhbCwgUlZJX2RlcGFydHVyZSkpICNiaW5kIFJWSSBmb3IgYXJyaXZhbHMgYW5kIGRlcGFydHVyZXMKClJWSV90YWJsZS5yIDwtIFJWSV90YWJsZVshZ3JlcCgiU3VyZmFjZSIsIHZhcmlhYmxlKV1bIWdyZXAoImxhZ2dlZCIsIHZhcmlhYmxlKV0KCiNjaGFuZ2Ugb3JkZXIgb2YgZmFjdG9yIGxldmVscwpSVklfdGFibGUuclssIHZhcmlhYmxlIDo9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gYygiQm90dG9tIiwgIm5vX2xhZyIsICJSYXciLCAiQ2hhbmdlIiwgInxDaGFuZ2V8IiwgIk1pbiIsICJNYXgiLCAiU2VhcyIpKV0KCnNhdmVSRFMoUlZJX3RhYmxlLCBmaWxlID0gaGVyZSgiTW9kZWxfcmVzdWx0cyIsICJSVklfdGFibGUucmRzIikpCgpnZ3Bsb3QoZGF0YSA9IFJWSV90YWJsZS5yLCBhZXMoeD12YXJpYWJsZSwgeSA9IHZhbHVlLCBmaWxsID0gYXJyaXZhbF9kZXBhcnR1cmUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzID0gYygiQm90dG9tIiwgIm5vX2xhZyIsICJSYXciLCAiQ2hhbmdlIiwgInxDaGFuZ2V8IiwgIk1pbiIsICJNYXgiLCAiU2VhcyIpLCAKICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvdHRvbSBUZW1wIiwgIk5vIExhZyIsICJSYXcgVGVtcCIsICJDaGFuZ2UgaW4gXG5UZW1wIiwgInwgQ2hhbmdlIGluXG4gVGVtcCB8IiwgIk1pbiBUZW1wIiwgIk1heCBUZW1wIiwgIlNlYXMiKSkgKwogIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSBWYXJpYWJsZXMiLCB5ID0gIlJlbGF0aXZlIFZhcmlhYmxlIEltcG9ydGFuY2UiKSAgKwogIHRoZW1lX2J3KCkKCmBgYAoKQW5vdGhlciB3YXkgdG8gdmlzdWFsaXplIGlzIHN0YWNrZWQgYmFyIHBsb3QuCgpgYGB7ciBSVkkgc3RhY2tlZCBwbG90fQojcHV0IGxldmVscyBpbnRvIGNvcnJlY3Qgb3JkZXIgZm9yIHZpZXdpbmcsIGFuZCBhZGQgZHVtbXkgbGV2ZWwgZm9yIGxlZ2VuZApSVklfYXJyaXZhbFssIHZhcmlhYmxlIDo9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gYygiQm90dG9tIiwgIlN1cmZhY2UiLCIgICIsICJSYXciLCAiQ2hhbmdlIiwgInxDaGFuZ2V8IiwiIiwgIm5vX2xhZyIsICJsYWdnZWQiLCAiTWluIiwgIk1heCIsICJTZWFzIikpXQpSVklfYXJyaXZhbFssIHR5cGUgOj0gZmFjdG9yKHR5cGUsIGxldmVscyA9IGMoIkRlcHRoIiwgIlRyYW5zZm9ybWF0aW9uIiwgIk1ldHJpYyIsICJsYWciKSldCgpSVklfYXJyaXZhbF9ub2xhZyA8LSBSVklfYXJyaXZhbFt0eXBlICE9ICJsYWciLF0KUlZJX2Fycml2YWxfbm9sYWdbLCB0eXBlIDo9IGZhY3Rvcih0eXBlLCBsZXZlbHMgPSBjKCJEZXB0aCIsICJUcmFuc2Zvcm1hdGlvbiIsICJNZXRyaWMiKSldWywgdmFyaWFibGUgOj0gZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJCb3R0b20iLCAiU3VyZmFjZSIsIiAgIiwgIlJhdyIsICJDaGFuZ2UiLCAifENoYW5nZXwiLCIiLCAiTWluIiwgIk1heCIsICJTZWFzIikpXQoKc2F2ZVJEUyhSVklfYXJyaXZhbF9ub2xhZywgaGVyZSgiTW9kZWxfcmVzdWx0cyIsICJSVklfYXJyaXZhbF9ub2xhZy5yZHMiKSkKCiNhbmQgYWdhaW4gZm9yIGRlcGFydHVyZQpSVklfZGVwYXJ0dXJlWywgdmFyaWFibGUgOj0gZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJCb3R0b20iLCAiU3VyZmFjZSIsIiAgIiwgIlJhdyIsICJDaGFuZ2UiLCAifENoYW5nZXwiLCIiLCAibm9fbGFnIiwgImxhZ2dlZCIsICJNaW4iLCAiTWF4IiwgIlNlYXMiKSldClJWSV9kZXBhcnR1cmVbLCB0eXBlIDo9IGZhY3Rvcih0eXBlLCBsZXZlbHMgPSBjKCJEZXB0aCIsICJUcmFuc2Zvcm1hdGlvbiIsICJNZXRyaWMiLCAibGFnIikpXQoKUlZJX2RlcGFydHVyZV9ub2xhZyA8LSBSVklfZGVwYXJ0dXJlW3R5cGUgIT0gImxhZyIsXQpSVklfZGVwYXJ0dXJlX25vbGFnWywgdHlwZSA6PSBmYWN0b3IodHlwZSwgbGV2ZWxzID0gYygiRGVwdGgiLCAiVHJhbnNmb3JtYXRpb24iLCAiTWV0cmljIikpXVssIHZhcmlhYmxlIDo9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gYygiQm90dG9tIiwgIlN1cmZhY2UiLCIgICIsICJSYXciLCAiQ2hhbmdlIiwgInxDaGFuZ2V8IiwiIiwgIk1pbiIsICJNYXgiLCAiU2VhcyIpKV0KCnNhdmVSRFMoUlZJX2RlcGFydHVyZV9ub2xhZywgaGVyZSgiTW9kZWxfcmVzdWx0cyIsICJSVklfZGVwYXJ0dXJlX25vbGFnLnJkcyIpKQoKCiNwbG90dGluZwpwYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgOCwgdHlwZSA9ICJjb250aW51b3VzIikKY29sb3JzIDwtIGMocGFsWzFdLCBwYWxbMl0sICIjRkZGRkZGIiwgcGFsWzNdLCBwYWxbNF0sIHBhbFs1XSwiI0ZGRkZGRiIsIHBhbFs2XSwgcGFsWzddLCBwYWxbOF0pCgojYXJyaXZhbHMKUlZJX2Fycml2YWxfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IFJWSV9hcnJpdmFsX25vbGFnLCBhZXMoeD10eXBlLCB5ID0gdmFsdWUsIGZpbGwgPSB2YXJpYWJsZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAsIHdpZHRoID0gMC44KSArCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3MgPSBjKCJEZXB0aCIsICJUcmFuc2Zvcm1hdGlvbiIsICJNZXRyaWMiKSwgbGFiZWxzID0gYygiRGVwdGgiLCAiVHJhbnNmb3JtYXRpb24iLCAiTWV0cmljIikpICsKICBsYWJzKHggPSAiVGVtcGVyYXR1cmUgVmFyaWFibGVzIiwgeSA9ICJSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEuNSksIAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoMC4yLCAnY20nKSwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJjZW50ZXIiLAogICAgICAgIGFzcGVjdC5yYXRpbyA9ICgxKSwKICAgICAgICAjLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICAgICAgICApICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQobmNvbD0xKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9ycywKICAgICAgICAgICAgICAgICAgICBkcm9wID0gRikKCiNkZXBhcnR1cmUKUlZJX2RlcGFydHVyZV9wbG90IDwtIGdncGxvdChkYXRhID0gUlZJX2RlcGFydHVyZV9ub2xhZywgYWVzKHg9dHlwZSwgeSA9IHZhbHVlLCBmaWxsID0gdmFyaWFibGUpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLCB3aWR0aCA9IDAuOCkgKwogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzID0gYygiRGVwdGgiLCAiVHJhbnNmb3JtYXRpb24iLCAiTWV0cmljIiksIGxhYmVscyA9IGMoIkRlcHRoIiwgIlRyYW5zZm9ybWF0aW9uIiwgIk1ldHJpYyIpKSArCiAgbGFicyh4ID0gIlRlbXBlcmF0dXJlIFZhcmlhYmxlcyIsIHkgPSAiUmVsYXRpdmUgVmFyaWFibGUgSW1wb3J0YW5jZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLjUpLCAKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGxlZ2VuZC5zcGFjaW5nLnggPSB1bml0KDAuMiwgJ2NtJyksCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgICBhc3BlY3QucmF0aW8gPSAoMSksCiAgICAgICAgIywgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgICAgICAgKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKG5jb2w9MSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMsCiAgICAgICAgICAgICAgICAgICAgZHJvcCA9IEYpCgpSVklfdGFibGUKUlZJX2Fycml2YWxfcGxvdApSVklfZGVwYXJ0dXJlX3Bsb3QKYGBgCk5leHQgc3RlcCBpcyB0byBhZGQgdGhlIGNvZWZmaWNpZW50cyBvbiB0byB0aGUgYmFyIGNoYXJ0LiBUbyBkbyB0aGlzLCBJIHdpbGwgbmVlZCB0byBzdW0gKGFpa2FrZSB3ZWlnaHQgb2YgbW9kZWwgaW5jbHVkaW5nIHZhcmlhYmxlIHggY29lZmZpY2llbnQpLiBJIHRoaW5rIHRoaXMgd2lsbCBiZSBlYXN5IGVub3VnaCBVc2luZyBhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuIGRhdGEgZnJhbWUuIEkgd2lsbCBhZGQgbmV3IGNvbHVtbiB0byBkYXRhIGZyYW1lIG9mIGFpa2Fpa2Ugd2VpZ2h0IHggY29lZmZpY2llbnQKCmBgYHtyIGF2ZyBjb2VmZmljaWVudHMgZm9yIGFycml2YWwgbW9kZWxzfQojZm9yIHNvbWUgcmVhc29uIHRoZSBjb2VmZmljaWVudCBpcyBhIGZhY3RvcgphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWyxjb2VmX251bSA6PSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcihjb2VmKSldCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bLGF3X2NvZWYgOj0gYWthaWtlX3dlaWdodCAqIGNvZWZfbnVtXQoKI2JvdHRvbSB0ZW1wZXJhdHVyZSBhdmcgY29lZmZpY2llbnQKYXJyaXZhbF9ib3R0b21fdGVtcF9hdmdfY29lZiA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzYnQiLCB2YXJpYWJsZSldJGNvZWZfbnVtKQoKI3N1cmZhY2UgdGVtcGVyYXR1cmUgYXZnIGNvZWZmaWNpZW50CmFycml2YWxfc3VyZmFjZV90ZW1wX2F2Z19jb2VmIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNzdCIsIHZhcmlhYmxlKV0kY29lZl9udW0pCgojcmF3IHNlYXNvbmFsaXR5IGF2ZyBjb2VmZmljaWVudAphcnJpdmFsX3NlYXNfcmF3X2F2Z19jb2VmIDwtIAogIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNlYXMiLCB2YXJpYWJsZSksIF1bIWdyZXAoImNoYW5nZSIsIHZhcmlhYmxlKV0kY29lZl9udW0pCgojbWF4IGFicyBjaGFuZ2UgYXZnIGNvZWZmaWNpZW50CmFycml2YWxfbWF4X2Fic19jaGFuZ2VfYXZnX2NvZWYgPC0gCiAgc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bZ3JlcCgibWF4X3MudF90ZW1wX2NoYW5nZV9hYnMiLCB2YXJpYWJsZSksIF0kY29lZl9udW0pCgoKYGBgCgpgYGB7ciBhdmcgY29lZmZpY2llbnRzIGZvciBkZXBhcnR1cmUgbW9kZWxzfQojZm9yIHNvbWUgcmVhc29uIHRoZSBjb2VmZmljaWVudCBpcyBhIGZhY3RvcgpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9ub21lYW5bLGNvZWZfbnVtIDo9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGNvZWYpKV0KZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuWyxhd19jb2VmIDo9IGFrYWlrZV93ZWlnaHQgKiBjb2VmX251bV0KCiNib3R0b20gdGVtcGVyYXR1cmUgYXZnIGNvZWZmaWNpZW50CmRlcGFydHVyZV9ib3R0b21fdGVtcF9hdmdfY29lZiA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNidCIsIHZhcmlhYmxlKV0kY29lZl9udW0pCgojc3VyZmFjZSB0ZW1wZXJhdHVyZSBhdmcgY29lZmZpY2llbnQKZGVwYXJ0dXJlX3N1cmZhY2VfdGVtcF9hdmdfY29lZiA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNzdCIsIHZhcmlhYmxlKV0kY29lZl9udW0pCgojcmF3IHNlYXNvbmFsaXR5IGF2ZyBjb2VmZmljaWVudApkZXBhcnR1cmVfc2Vhc19yYXdfYXZnX2NvZWYgPC0gCiAgc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX25vbWVhbltncmVwKCJzZWFzIiwgdmFyaWFibGUpLCBdWyFncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSldJGNvZWZfbnVtKQoKI21pbiBjaGFuZ2UgYXZnIGNvZWZmaWNpZW50CmRlcGFydHVyZV9taW5fYWJzX2NoYW5nZV9hdmdfY29lZiA8LSAKICBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoIm1pbl9zLnRfdGVtcF9jaGFuZ2UiLCB2YXJpYWJsZSksIF1bIWdyZXAoImFicyIsIHZhcmlhYmxlKV0kY29lZl9udW0pCgojc2VhcyBjaGFuZ2UgYXZnIGNvZWZmaWNpZW50CmRlcGFydHVyZV9zZWFzX2NoYW5nZV9hdmdfY29lZiA8LSAKICBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fbm9tZWFuW2dyZXAoInNlYXNfcy50X3RlbXBfY2hhbmdlIiwgdmFyaWFibGUpLCBdWyFncmVwKCJhYnMiLCB2YXJpYWJsZSldJGNvZWZfbnVtKQoKCmBgYAoKCioqKioqKioqKioqKioqKioqKioqKioqKioKKioqKioqKioqKioqKioqKioqKioqKioqKgoqKioqKioqKioqKioqKioqKioqKioqKioqCioqKioqKioqKioqKioqKioqKioqKioqKioKKFRoZXNlIGFuYWx5c2VzIHdlcmUgaXJyZWxldmFudCBhbmQgdGhlcmVmb3JlIG5vdCByZXBlYXRlZCBmb3IgcmV2aXNpb25zKQojI1doYXQgaWYgd2UgcnVuIHRoZXNlIG1vZGVscyB3aXRoIGZpc2ggb25seT8gTm8gdHJhaXRzPyBIb3cgZG8gaW52ZXJ0cyBjaGFuZ2UgdGhlIHN0b3J5PyBCZWNhdXNlIGl0IGxvb2tzIGxpa2UgYWJvdmUsIG5vdCBhIHRvbiBvZiBpbnZlcnRlYnJhdGVzIGFyZSBnb2luZyBpbiBhbmQgb3V0LiAKCmBgYHtyIGZpc2ggb25seX0KI2xpc3Qgb2YgZmlzaCBuYW1lcyBmcm9tIHRyYWl0IGRhdGFiYXNlCnRyYWl0cyA8LSBmcmVhZCgiVHJhaXRDb2xsZWN0aW9uRmlzaE5BdGxhbnRpY05FUGFjaWZpY0NvbnRTaGVsZiAoMykuY3N2IikKCiNtYWtlIGZpc2ggbm8gZmlzaCBrZXkKZmlzaCA8LSBkYXRhLnRhYmxlKHNwcCA9IHVuaXF1ZSh0cmFpdHMkdGF4b24pLCBmaXNoID0gIlkiKQoKI2NvbWJpbmUgd2l0aCBzcHAgbWFzdGVyCnNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZF9maXNob25seSA8LSBtZXJnZShzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWQsIGZpc2gsIGFsbC54ID0gVCkKCiNnZXQgcmlkIG9mIGFueSByb3dzIHRoYXQgYXJlbid0IG9ic2VydmF0aW9ucyBvZiBmaXNoCnNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZF9maXNob25seTIgPC0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkX2Zpc2hvbmx5W2Zpc2ggPT0gIlkiLF0KCmBgYAoKUnVubmluZyBtb2RlbHMgZm9yIGZpc2ggb25seQoKYGBge3IgYXJyaXZhbCBtb2RlbHMgd2l0aG91dCB0cmFpdHMgZm9yIGZpc2ggb25seX0KCiNuYW1lcyBvZiBzY2FsZWQgY29sdW1ucwpzY2FsZWRfY29scyA8LSBncmVwKCIqX3NjYWxlZCIsIG5hbWVzKHNwcF9tYXN0ZXJfenRlbXBfc2V1c19idW95X3NjYWxlZF9maXNob25seTIpLCB2YWx1ZSA9IFQpCgojZ29pbmcgdG8gbWFrZSBsb29wIHRvIG1ha2UgYWxsIG1vZGVscyBJIG5lZWQgdG8gbG9vayBhdCB3aXRoIHNpbmdsZSB2YXJpYWJsZXMKdmFyaWFibGVzX3NjYWxlZCA8LSBjb2xuYW1lcyhzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWRfZmlzaG9ubHkyWyxzY2FsZWRfY29scywgd2l0aCA9IEZBTFNFXSkKCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5IDwtIGFzLmRhdGEudGFibGUobWF0cml4KG5yb3cgPSBsZW5ndGgodmFyaWFibGVzX3NjYWxlZCkpKQphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVssIHZhcmlhYmxlOj1hcy5mYWN0b3IoVjEpXVssIGNvZWY6PWFzLm51bWVyaWMoVjEpXVssIHBfdmFsdWU6PWFzLm51bWVyaWMoVjEpXVssIEFJQ2M6PWFzLm51bWVyaWMoVjEpXQphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVssIFYxIDo9IE5VTExdCgpmb3IgKGkgaW4gMTpsZW5ndGgodmFyaWFibGVzX3NjYWxlZCkpewogIG1vZCA8LSBnbG1lcihjb2wgfiBnZXQodmFyaWFibGVzX3NjYWxlZFtpXSkgKyAoMXxyZWcpICsgKDF8c3BwKSwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWRfZmlzaG9ubHkyLCBuQUdRID0gMCkKICBhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVtpLHZhcmlhYmxlIDo9IHZhcmlhYmxlc19zY2FsZWRbaV1dCiAgYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlbaSxjb2VmIDo9IGNvZWYoc3VtbWFyeShtb2QpKVssIkVzdGltYXRlIl1bMl1dCiAgYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlbaSxwX3ZhbHVlIDo9IGNvZWYoc3VtbWFyeShtb2QpKVssIlByKD58enwpIl1bMl1dCiAgYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlbaSxBSUNjIDo9IEFJQ2MobW9kKV0KICAKICBwcmludChwYXN0ZShpLCBsZW5ndGgodmFyaWFibGVzX3NjYWxlZCksIHNlcCA9ICIvIikpCiAgICAKfQoKI2J5IHNldHRpbmcgbkFDUSB0byAwLCBhbGwgbW9kZWxzIGNvbnZlcmdlZAoKCmBgYAoKZGVwYXJ0dXJlIE1vZGVscyB3aXRob3V0IFRyYWl0cwpgYGB7ciBkZXBhcnR1cmUgbW9kZWxzIHdpdGhvdXQgdHJhaXRzIGZvciBmaXNoIG9ubHl9CiNzZWUgc2V0dXAgYWJvdmUKCmRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHkgPC0gYXMuZGF0YS50YWJsZShtYXRyaXgobnJvdyA9IGxlbmd0aCh2YXJpYWJsZXNfc2NhbGVkKSkpCmRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlbLCB2YXJpYWJsZTo9YXMuZmFjdG9yKFYxKV1bLCBjb2VmOj1hcy5udW1lcmljKFYxKV1bLCBwX3ZhbHVlOj1hcy5udW1lcmljKFYxKV1bLCBBSUNjOj1hcy5udW1lcmljKFYxKV0KZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVssIFYxIDo9IE5VTExdCgpmb3IgKGkgaW4gMTpsZW5ndGgodmFyaWFibGVzX3NjYWxlZCkpewogIG1vZCA8LSBnbG1lcihub3dfZXh0IH4gZ2V0KHZhcmlhYmxlc19zY2FsZWRbaV0pICsgKDF8cmVnKSArICgxfHNwcCksIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gc3BwX21hc3Rlcl96dGVtcF9zZXVzX2J1b3lfc2NhbGVkX2Zpc2hvbmx5MiwgbkFHUSA9IDApCiAgZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVtpLHZhcmlhYmxlIDo9IHZhcmlhYmxlc19zY2FsZWRbaV1dCiAgZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVtpLGNvZWYgOj0gY29lZihzdW1tYXJ5KG1vZCkpWywiRXN0aW1hdGUiXVsyXV0KICBkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5W2kscF92YWx1ZSA6PSBjb2VmKHN1bW1hcnkobW9kKSlbLCJQcig+fHp8KSJdWzJdXQogIGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlbaSxBSUNjIDo9IEFJQ2MobW9kKV0KICAKICBwcmludChwYXN0ZShpLCBsZW5ndGgodmFyaWFibGVzX3NjYWxlZCksIHNlcCA9ICIvIikpCiAgICAKfQoKI2J5IHNldHRpbmcgbkFDUSB0byAwLCBhbGwgbW9kZWxzIGNvbnZlcmdlZAoKCmBgYAoKUmVsYXRpdmUgVmFyaWFibGUgSW1wb3J0YW5jZQpgYGB7ciBnZXQgcmlkIG9mIGFueSBtb2RlbHMgdXNpbmcgbWVhbiBmb3IgZmlzaCBvbmx5fQphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW4gPC0gYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlbIWdyZXBsKCJtZWFuIix2YXJpYWJsZSksXQoKZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW4gPC0gZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seVshZ3JlcGwoIm1lYW4iLHZhcmlhYmxlKSxdCgojY29tcGFyaXNvbiB0byBudWxsCmNvbF9tb2RfbnVsbCA8LSBnbG1lcihjb2wgfiAoMXxyZWcpICsgKDF8c3BwKSwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWRfZmlzaG9ubHkyLCBuQUdRID0gMCkKQUlDYyhjb2xfbW9kX251bGwpLW1pbihhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW4kQUlDYykKCmV4dF9tb2RfbnVsbCA8LSBnbG1lcihleHQgfiAoMXxyZWcpICsgKDF8c3BwKSwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBzcHBfbWFzdGVyX3p0ZW1wX3NldXNfYnVveV9zY2FsZWRfZmlzaG9ubHkyLCBuQUdRID0gMCkKQUlDYyhleHRfbW9kX251bGwpLW1pbihkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbiRBSUNjKQpgYGAKClJlbGF0aXZlIFZhcmlhYmxlIEltcG9ydGFuY2UgZm9yIGFycml2YWwgTW9kZWxzCmBgYHtyIFJWSSBhcnJpdmFsIGZvciBmaXNoIG9ubHl9CiNhZGQg4oiGQUlDIHRvIHRhYmxlcwptaW5fY29sX0FJQ2NfZmlzaG9ubHkgPC0gbWluKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhblssIEFJQ2NdKQphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bLCJkZWx0YUFJQ2MiIDo9IChBSUNjIC0gbWluX2NvbF9BSUNjX2Zpc2hvbmx5KV0KCiNhZGQgcmVsYXRpdmUgbGlrZWxpaG9vZCBleHAoIC0wLjUgKiDiiIZBSUMgc2NvcmUgZm9yIHRoYXQgbW9kZWwpCmFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhblssInJlbF9saWtlbGlob29kIiA6PSBleHAoKC0wLjUgKiBkZWx0YUFJQ2MpKV0KI3N1bSByZWxhdGl2ZSBsaWtlbGlob29kcyBhY3Jvc3MgYWxsIG1vZGVscwphcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW4ubGlrZWxpaG9vZHN1bSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuWywgcmVsX2xpa2VsaWhvb2RdKQojQWthaWtlIHdlaWdodCBmb3IgYSBtb2RlbCBpcyB0aGlzIHJlbF9saWtlbGlob29kIGRldmlkZWQgYnkgdGhlIHN1bSBvZiB0aGVzZSB2YWx1ZXMgYWNyb3NzIGFsbCBtb2RlbHMKYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuWywiYWthaWtlX3dlaWdodCIgOj0gcmVsX2xpa2VsaWhvb2QvYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuLmxpa2VsaWhvb2RzdW1dCgojSSB3YW50IHRvIGxvb2sgYXQgcmVsYXRpdmUgaW1wb3J0YW5jZSBGT1IgCiNib3R0b20vc3VyZmFjZSAoYm90dG9tID0gaW5jbHVkZXMgc2J0LCBncmVwbCgic2J0IiwgdmFyaWFibGUpKQpjb2xfYm90dG9tX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJzYnQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKY29sX3N1cmZhY2VfaW1wb3J0YW5jZV9maXNob25seSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoInNzdCIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI2xhZy9ub3QgbGFnZ2VkIChncmVwbCgibGFnIiwgdmFyaWFibGUpKQpjb2xfbGFnX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKY29sX25vbGFnX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhblshZ3JlcCgibGFnIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgojYWJzb2x1dGUgKGdyZXBsKCJhYnMiLCB2YXJpYWJsZSkpCmNvbF9hYnNfaW1wb3J0YW5jZV9maXNob25seSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImFicyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI3JhdyAoIWdyZXBsKCJjaGFuZ2UiKSkKY29sX3Jhd19pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bIWdyZXAoImNoYW5nZSIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI2NoYW5nZSAoZ3JlcGwoImNoYW5nZSIsIHZhcmlhYmxlKSwgKCFncmVwbCgiYWJzIikpKQpjb2xfY2hhbmdlX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJjaGFuZ2UiLCB2YXJpYWJsZSksIF1bIWdyZXAoImFicyIsIHZhcmlhYmxlKSxdJGFrYWlrZV93ZWlnaHQpCgojdHlwZSBvZiB0ZW1wIHZhcmlhYmxlIChtYXgsIG1pbiwgc2VhcykKY29sX21heF90ZW1wX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJtYXgiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKY29sX21pbl90ZW1wX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJtaW4iLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKY29sX3NlYXNfdGVtcF9pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bZ3JlcCgic2VhcyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpgYGAKClJlbGF0aXZlIFZhcmlhYmxlIEltcG9ydGFuY2UgZm9yIGRlcGFydHVyZSBNb2RlbHMKYGBge3IgUlZJIGRlcGFydHVyZSBmb3IgZmlzaCBvbmx5fQojYWRkIOKIhkFJQyB0byB0YWJsZXMKbWluX2V4dF9BSUNjX2Zpc2hvbmx5IDwtIG1pbihkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhblssIEFJQ2NdKQpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhblssImRlbHRhQUlDYyIgOj0gKEFJQ2MgLSBtaW5fZXh0X0FJQ2NfZmlzaG9ubHkpXQoKI2FkZCByZWxhdGl2ZSBsaWtlbGlob29kIGV4cCggLTAuNSAqIOKIhkFJQyBzY29yZSBmb3IgdGhhdCBtb2RlbCkKZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bLCJyZWxfbGlrZWxpaG9vZCIgOj0gZXhwKCgtMC41ICogZGVsdGFBSUNjKSldCiNzdW0gcmVsYXRpdmUgbGlrZWxpaG9vZHMgYWNyb3NzIGFsbCBtb2RlbHMKZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW4ubGlrZWxpaG9vZHN1bSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bLCByZWxfbGlrZWxpaG9vZF0pCiNBa2Fpa2Ugd2VpZ2h0IGZvciBhIG1vZGVsIGlzIHRoaXMgcmVsX2xpa2VsaWhvb2QgZGV2aWRlZCBieSB0aGUgc3VtIG9mIHRoZXNlIHZhbHVlcyBhY3Jvc3MgYWxsIG1vZGVscwpkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhblssImFrYWlrZV93ZWlnaHQiIDo9IHJlbF9saWtlbGlob29kL2RlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuLmxpa2VsaWhvb2RzdW1dCgojSSB3YW50IHRvIGxvb2sgYXQgcmVsYXRpdmUgaW1wb3J0YW5jZSBGT1IgCiNib3R0b20vc3VyZmFjZSAoYm90dG9tID0gaW5jbHVkZXMgc2J0LCBncmVwbCgic2J0IiwgdmFyaWFibGUpKQpleHRfYm90dG9tX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoInNidCIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpleHRfc3VyZmFjZV9pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJzc3QiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCiNsYWcvbm90IGxhZ2dlZCAoZ3JlcGwoImxhZyIsIHZhcmlhYmxlKSkKZXh0X2xhZ19pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKZXh0X25vbGFnX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuWyFncmVwKCJsYWciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCiNhYnNvbHV0ZSAoZ3JlcGwoImFicyIsIHZhcmlhYmxlKSkKZXh0X2Fic19pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJhYnMiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKCiNyYXcgKCFncmVwbCgiY2hhbmdlIikpCmV4dF9yYXdfaW1wb3J0YW5jZV9maXNob25seSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bIWdyZXAoImNoYW5nZSIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQoKI2NoYW5nZSAoZ3JlcGwoImNoYW5nZSIsIHZhcmlhYmxlKSwgKCFncmVwbCgiYWJzIikpKQpleHRfY2hhbmdlX2ltcG9ydGFuY2VfZmlzaG9ubHkgPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImNoYW5nZSIsIHZhcmlhYmxlKSwgXVshZ3JlcCgiYWJzIiwgdmFyaWFibGUpLF0kYWthaWtlX3dlaWdodCkKCiN0eXBlIG9mIHRlbXAgdmFyaWFibGUgKG1heCwgbWluLCBzZWFzKQpleHRfbWF4X3RlbXBfaW1wb3J0YW5jZV9maXNob25seSA8LSBzdW0oZGVwYXJ0dXJlX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bZ3JlcCgibWF4IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmV4dF9taW5fdGVtcF9pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJtaW4iLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKZXh0X3NlYXNfdGVtcF9pbXBvcnRhbmNlX2Zpc2hvbmx5IDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJzZWFzIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmBgYAoKTGV0J3Mgc2VlIGhvdyB0aGUgUlZJIGltcG9ydGFuY2UgdmFyaWVzIGJ5IGxvb2tpbmcgYXQgc3BlY2lmaWMgbGFnIHZhbHVlcwpgYGB7ciBtYWtlIGEgcGxvdCBoZXJlIGZvciB2YXJpYWJpbGl0eSBhY3Jvc3MgbGFnIHZhbHVlcyBmb3IgZmlzaCBvbmx5fQojZmlyc3QsIHRhYmxlIGZvciBsYWdzCmxhZ3Nfdl9SVklfc3BwcmFuZG9tX3NjYWxlZF9maXNob25seSA8LSBkYXRhLnRhYmxlKGNvbF9sYWcgPSBjKDA6OSksIGNvbF9SVkkgPSAwLCBkZXBhcnR1cmVfUlZJID0gMCkKI2Fycml2YWwKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzEsMl0gPC0gMS1zdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX3ZfUlZJX3NwcHJhbmRvbV9zY2FsZWRfZmlzaG9ubHlbMiwyXSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzEiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzMsMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWcyIiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3Nfdl9SVklfc3BwcmFuZG9tX3NjYWxlZF9maXNob25seVs0LDJdIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bZ3JlcCgibGFnMyIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX3ZfUlZJX3NwcHJhbmRvbV9zY2FsZWRfZmlzaG9ubHlbNSwyXSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzYsMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWc1IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3Nfdl9SVklfc3BwcmFuZG9tX3NjYWxlZF9maXNob25seVs3LDJdIDwtIHN1bShhcnJpdmFsX21vZGVsX2NvbXBhcmlzb25fc3BwcmFuZG9tX3NjYWxlZF9zZXVzX3VwZGF0ZV9maXNob25seV9ub21lYW5bZ3JlcCgibGFnNiIsIHZhcmlhYmxlKSwgXSRha2Fpa2Vfd2VpZ2h0KQpsYWdzX3ZfUlZJX3NwcHJhbmRvbV9zY2FsZWRfZmlzaG9ubHlbOCwyXSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzksMl0gPC0gc3VtKGFycml2YWxfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWc4IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCmxhZ3Nfdl9SVklfc3BwcmFuZG9tX3NjYWxlZF9maXNob25seVsxMCwyXSA8LSBzdW0oYXJyaXZhbF9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzkiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKI2RlcGFydHVyZQpsYWdzX3ZfUlZJX3NwcHJhbmRvbV9zY2FsZWRfZmlzaG9ubHlbMSwzXSA8LSAxLXN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzIsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzEiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzMsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzIiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzQsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzMiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzUsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzQiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzYsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzUiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzcsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzYiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzgsM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzciLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzksM10gPC0gc3VtKGRlcGFydHVyZV9tb2RlbF9jb21wYXJpc29uX3NwcHJhbmRvbV9zY2FsZWRfc2V1c191cGRhdGVfZmlzaG9ubHlfbm9tZWFuW2dyZXAoImxhZzgiLCB2YXJpYWJsZSksIF0kYWthaWtlX3dlaWdodCkKbGFnc192X1JWSV9zcHByYW5kb21fc2NhbGVkX2Zpc2hvbmx5WzEwLDNdIDwtIHN1bShkZXBhcnR1cmVfbW9kZWxfY29tcGFyaXNvbl9zcHByYW5kb21fc2NhbGVkX3NldXNfdXBkYXRlX2Zpc2hvbmx5X25vbWVhbltncmVwKCJsYWc5IiwgdmFyaWFibGUpLCBdJGFrYWlrZV93ZWlnaHQpCgpnZ3Bsb3QoZGF0YSA9IGxhZ3Nfdl9SVklfc3BwcmFuZG9tX3NjYWxlZF9maXNob25seSwgYWVzKHggPSBjb2xfbGFnKSkgKwogIGdlb21fbGluZShhZXMoeSA9IGNvbF9SVkkpLCBjb2wgPSAiYmx1ZSIpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBkZXBhcnR1cmVfUlZJKSwgY29sID0gInJlZCIpICsKICBsYWJzKHggPSAiTGFnIiwgeSA9ICJSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIikgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKCkgKyAjaG93IHRvIG1ha2UgYSBsZWdlbmQKICB0aGVtZV9idygpCmBgYAoKVGFibGUgZm9yIFJWSSBkYXRhIGZvciBhcnJpdmFsCmBgYHtyIHB1dCBSVklzIGZvciBhcnJpdmFsIGludG8gZGF0YSB0YWJsZSBmb3IgZmlzaCBvbmx5fQpjb2xfZXh0IDwtIGMoImNvbCIsImNvbCIsImNvbCIsImNvbCIsImNvbCIsICJjb2wiLCJjb2wiLCAiY29sIiwgImNvbCIsImNvbCIpCnR5cGUgPC0gYygiZGVwdGgiLCAiZGVwdGgiLCAibGFnIiwgImxhZyIsICJDaGFuZ2U/IiwgIkNoYW5nZT8iLCAiQ2hhbmdlPyIsICJUZW1wIiwgIlRlbXAiLCAiVGVtcCIpCnZhcmlhYmxlIDwtIGMoImJvdHRvbSIsICJzdXJmYWNlIiwgIm5vX2xhZyIsICJsYWdnZWQiLCAiYWJzb2x1dGVfdmFsdWVfY2hhbmdlIiwgImNoYW5nZSIsICJyYXciLCAiTWluIiwgIk1heCIsICJTZWFzIikKdmFsdWUgPC0gYyhjb2xfYm90dG9tX2ltcG9ydGFuY2VfZmlzaG9ubHksIGNvbF9zdXJmYWNlX2ltcG9ydGFuY2VfZmlzaG9ubHksIGNvbF9ub2xhZ19pbXBvcnRhbmNlX2Zpc2hvbmx5LCBjb2xfbGFnX2ltcG9ydGFuY2VfZmlzaG9ubHksIGNvbF9hYnNfaW1wb3J0YW5jZV9maXNob25seSwgY29sX2NoYW5nZV9pbXBvcnRhbmNlX2Zpc2hvbmx5LCBjb2xfcmF3X2ltcG9ydGFuY2VfZmlzaG9ubHksIGNvbF9taW5fdGVtcF9pbXBvcnRhbmNlX2Zpc2hvbmx5LCBjb2xfbWF4X3RlbXBfaW1wb3J0YW5jZV9maXNob25seSwgY29sX3NlYXNfdGVtcF9pbXBvcnRhbmNlX2Zpc2hvbmx5KQoKUlZJX2NvbF9maXNob25seSA8LSBkYXRhLnRhYmxlKGNvbF9leHQsIHR5cGUsIHZhcmlhYmxlLCB2YWx1ZSkKYGBgCgpUYWJsZSBmb3IgUlZJIGRhdGEgZm9yIGRlcGFydHVyZQpgYGB7ciBwdXQgUlZJcyBmb3IgZGVwYXJ0dXJlIGludG8gZGF0YSB0YWJsZSBmb3IgZmlzaCBvbmx5fQpjb2xfZXh0IDwtIGMoImV4dCIsImV4dCIsImV4dCIsImV4dCIsImV4dCIsICJleHQiLCAiZXh0IiwgImV4dCIsICJleHQiLCAiZXh0IikKdHlwZSA8LSBjKCJkZXB0aCIsICJkZXB0aCIsICJsYWciLCAibGFnIiwgIkNoYW5nZT8iLCAiQ2hhbmdlPyIsICJDaGFuZ2U/IiwgIlRlbXAiLCAiVGVtcCIsICJUZW1wIikKdmFyaWFibGUgPC0gYygiYm90dG9tIiwgInN1cmZhY2UiLCAibm9fbGFnIiwgImxhZ2dlZCIsICJhYnNvbHV0ZV92YWx1ZV9jaGFuZ2UiLCAiY2hhbmdlIiwgInJhdyIsICJNaW4iLCAiTWF4IiwgIlNlYXMiKQp2YWx1ZSA8LSBjKGV4dF9ib3R0b21faW1wb3J0YW5jZV9maXNob25seSwgZXh0X3N1cmZhY2VfaW1wb3J0YW5jZV9maXNob25seSwgZXh0X25vbGFnX2ltcG9ydGFuY2VfZmlzaG9ubHksIGV4dF9sYWdfaW1wb3J0YW5jZV9maXNob25seSwgZXh0X2Fic19pbXBvcnRhbmNlX2Zpc2hvbmx5LCBleHRfY2hhbmdlX2ltcG9ydGFuY2VfZmlzaG9ubHksIGV4dF9yYXdfaW1wb3J0YW5jZV9maXNob25seSwgZXh0X21pbl90ZW1wX2ltcG9ydGFuY2VfZmlzaG9ubHksIGV4dF9tYXhfdGVtcF9pbXBvcnRhbmNlX2Zpc2hvbmx5LCBleHRfc2Vhc190ZW1wX2ltcG9ydGFuY2VfZmlzaG9ubHkpCgpSVklfZXh0X2Zpc2hvbmx5IDwtIGRhdGEudGFibGUoY29sX2V4dCwgdHlwZSwgdmFyaWFibGUsIHZhbHVlKQpgYGAKCk1lcmdlIFJWSSB0YWJsZXMgZm9yIGFycml2YWwgYW5kIGRlcGFydHVyZSwgYW5kIHRoZW4gZ3JhcGgKYGBge3IgbWVyZ2UgUlZJIHRhYmxlcyBhbmQgcGxvdCBmb3IgZmlzaCBvbmx5fQpSVklfdGFibGVfZmlzaG9ubHkgPC0gYXMuZGF0YS50YWJsZShyYmluZChSVklfY29sX2Zpc2hvbmx5LCBSVklfZXh0X2Zpc2hvbmx5KSkgI2JpbmQgUlZJIGZvciBhcnJpdmFscyBhbmQgZGVwYXJ0dXJlcwoKUlZJX3RhYmxlLnJfZmlzaG9ubHkgPC0gUlZJX3RhYmxlX2Zpc2hvbmx5WyFncmVwKCJzdXJmYWNlIiwgdmFyaWFibGUpXVshZ3JlcCgibGFnZ2VkIiwgdmFyaWFibGUpXQoKI2NoYW5nZSBvcmRlciBvZiBmYWN0b3IgbGV2ZWxzClJWSV90YWJsZS5yX2Zpc2hvbmx5WywgdmFyaWFibGUgOj0gZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJib3R0b20iLCAibm9fbGFnIiwgInJhdyIsICJjaGFuZ2UiLCAiYWJzb2x1dGVfdmFsdWVfY2hhbmdlIiwgIk1pbiIsICJNYXgiLCAiU2VhcyIpKV0KCnNhdmUoUlZJX3RhYmxlX2Zpc2hvbmx5LCBmaWxlID0gIlJWSV90YWJsZV9maXNob25seS5SZGF0YSIpCgpnZ3Bsb3QoZGF0YSA9IFJWSV90YWJsZS5yX2Zpc2hvbmx5LCBhZXMoeD12YXJpYWJsZSwgeSA9IHZhbHVlLCBmaWxsID0gY29sX2V4dCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3MgPSBjKCJib3R0b20iLCAibm9fbGFnIiwgInJhdyIsICJjaGFuZ2UiLCAiYWJzb2x1dGVfdmFsdWVfY2hhbmdlIiwgIk1pbiIsICJNYXgiLCAiU2VhcyIpLCBsYWJlbHMgPSBjKCJCb3R0b20gVGVtcCIsICJObyBMYWciLCAiUmF3IFRlbXAiLCAiQ2hhbmdlIGluIFxuVGVtcCIsICJ8IENoYW5nZSBpblxuIFRlbXAgfCIsICJNaW4gVGVtcCIsICJNYXggVGVtcCIsICJTZWFzIikpICsKICBsYWJzKHggPSAiVGVtcGVyYXR1cmUgVmFyaWFibGVzIiwgeSA9ICJSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIikgICsKICB0aGVtZV9idygpCgpgYGAKCkFub3RoZXIgd2F5IHRvIHZpc3VhbGl6ZSBpcyBzdGFja2VkIGJhciBwbG90LgoKYGBge3IgUlZJIHN0YWNrZWQgcGxvdCBmb3IgZmlzaCBvbmx5fQojcHV0IGxldmVscyBpbnRvIGNvcnJlY3Qgb3JkZXIgZm9yIHZpZXdpbmcKUlZJX3RhYmxlX2Zpc2hvbmx5WywgdmFyaWFibGUgOj0gZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJib3R0b20iLCAic3VyZmFjZSIsICJhYnNvbHV0ZV92YWx1ZV9jaGFuZ2UiLCAiY2hhbmdlIiwgInJhdyIsICJub19sYWciLCAibGFnZ2VkIiwgIk1pbiIsICJNYXgiLCAiU2VhcyIpKV0KI21ha2UgdHlwZXMgZmFjdG9ycyBhcyB3ZWxsClJWSV90YWJsZV9maXNob25seVssdHlwZSA6PSBhcy5mYWN0b3IodHlwZSldCgojYXJyaXZhbApSVklfY29sX3Bsb3RfZmlzaG9ubHkgPC0gZ2dwbG90KGRhdGEgPSBSVklfdGFibGVfZmlzaG9ubHlbY29sX2V4dCA9PSAiY29sIixdLCBhZXMoeD10eXBlLCB5ID0gdmFsdWUsIGZpbGwgPSB2YXJpYWJsZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzID0gYygiQ2hhbmdlPyIsICJkZXB0aCIsICJsYWciLCAiVGVtcCIpLCBsYWJlbHMgPSBjKCJDaGFuZ2UgaW5cbnRlbXA/IiwgIk1ldHJpY1xuRGVwdGgiLCAiTGFnZ2VkPyIsICJUZW1wIikpICsKICBsYWJzKHggPSAiVGVtcGVyYXR1cmUgVmFyaWFibGVzIiwgeSA9ICJSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjIpCiAgICAgICAgIywgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgICAgICAgKQoKI2RlcGFydHVyZQpSVklfZXh0X3Bsb3RfZmlzaG9ubHkgPC0gZ2dwbG90KGRhdGEgPSBSVklfdGFibGVfZmlzaG9ubHlbY29sX2V4dCA9PSAiZXh0IixdLCBhZXMoeD10eXBlLCB5ID0gdmFsdWUsIGZpbGwgPSB2YXJpYWJsZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoYnJlYWtzID0gYygiQ2hhbmdlPyIsICJkZXB0aCIsICJsYWciLCAiVGVtcCIpLCBsYWJlbHMgPSBjKCJDaGFuZ2UgaW5cbnRlbXA/IiwgIk1ldHJpY1xuRGVwdGgiLCAiTGFnZ2VkPyIsICJUZW1wIikpICsKICBsYWJzKHggPSAiVGVtcGVyYXR1cmUgVmFyaWFibGVzIiwgeSA9ICJSZWxhdGl2ZSBWYXJpYWJsZSBJbXBvcnRhbmNlIikgKwogIHRoZW1lX2NsYXNzaWMoKSAgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIyKQogICAgICAgICMsIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICAgICAgICkKClJWSV90YWJsZV9maXNob25seQpSVklfY29sX3Bsb3RfZmlzaG9ubHkKUlZJX2V4dF9wbG90X2Zpc2hvbmx5CgoKYGBgCg==